如題,有三個點的曲線(開始點,中間點,結束點)
5個點:(開始點,結束點,三個中間點)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BezierCurve : MonoBehaviour
{
public Transform _startTra;//起始點
public Transform _centerTra;//中間點(隨意即可)
public Transform _endTra;//終結點
//編輯器畫線
void OnDrawGizmos()
{
List<Vector3> m_pathPointList = new List<Vector3>();
m_pathPointList.AddRange(GetPathPoints(_startTra.position, _endTra.position, _centerTra.position, 20));
Gizmos.color = Color.yellow;
for (int i = 0; i < m_pathPointList.Count - 1; i++)
{
Gizmos.DrawLine(m_pathPointList[i], m_pathPointList[i + 1]);
}
}
//一個額外點的貝薩爾曲線(即拋物線)
public static Vector3[] GetPathPoints(Vector3 startPos, Vector3 endPos, Vector3 centerPos, int needPointNumber = 20)
{
//爲了節省性能
//將其轉化成;一個float,可以進行差值運算,否則結果爲0
float number = (float)needPointNumber;
//定義一個數組,用來存放路徑點,他的長度是從0 - needPointNumber的長度,及從0-1
Vector3[] targetPosArr = new Vector3[needPointNumber + 1];
//只有在等於needPointNumber時Lerp()中最後一項的值才爲1,所有比needPointNumber數多1
for (int i = 0; i <= needPointNumber; i++)
{
//第一層
Vector3 one1 = Vector3.Lerp(startPos, centerPos, i / number);
Vector3 one2 = Vector3.Lerp(centerPos, endPos, i / number);
//目標層
Vector3 targetPos = Vector3.Lerp(one1, one2, i / number);
//將目標層放入我們的路徑點中
targetPosArr[i] = targetPos;
}
//在for循環結束之後得到所有的路徑點
return targetPosArr;
}
///
/// 將目標物體從開始點移動到目標點通過平滑的曲線
///
/// 你要移動的目標物體
/// 目標物體的開始點
/// 目標物體的結束點
/// 三個中間點
/// 你最終得到的路徑點的中間數,默認是20,數量越大麴線越平滑,越小越線性
///
public static Vector3[] GetPathPoints(Transform start, Transform end, Transform[] threeCenterPosArr, int needPointNumber = 20)
{
//爲了節省性能
//將其轉化成;一個float,可以進行差值運算,否則結果爲0
float number = (float)needPointNumber;
//定義一個數組,用來存放路徑點,他的長度是從0 - needPointNumber的長度,及從0-1
Vector3[] targetPosArr = new Vector3[needPointNumber + 1];
//只有在等於needPointNumber時Lerp()中最後一項的值才爲1,所有比needPointNumber數多1
for (int i = 0; i <= needPointNumber; i++)
{
//第一層
Vector3 one1 = Vector3.Lerp(start.position, threeCenterPosArr[0].position, i / number);
Vector3 one2 = Vector3.Lerp(threeCenterPosArr[0].position, threeCenterPosArr[1].position, i / number);
Vector3 one3 = Vector3.Lerp(threeCenterPosArr[1].position, threeCenterPosArr[2].position, i / number);
Vector3 one4 = Vector3.Lerp(threeCenterPosArr[2].position, end.position, i / number);
//第二層
Vector3 two1 = Vector3.Lerp(one1, one2, i / number);
Vector3 two2 = Vector3.Lerp(one2, one3, i / number);
Vector3 two3 = Vector3.Lerp(one3, one4, i / number);
//第三層
Vector3 three1 = Vector3.Lerp(two1, two2, i / number);
Vector3 three2 = Vector3.Lerp(two2, two3, i / number);
//目標層
Vector3 targetPos = Vector3.Lerp(three1, three2, i / number);
//將目標層放入我們的路徑點中
targetPosArr[i] = targetPos;
}
//在for循環結束之後得到所有的路徑點
return targetPosArr;
}
//額外的重載方法,就不仔細介紹了
public static Vector3[] GetPathPoints(Vector3 startPos, Vector3 endPos, Vector3[] threeCenterPosArr, int needPointNumber = 20)
{
float number = (float)needPointNumber;
Vector3[] targetPosArr = new Vector3[needPointNumber + 1];
for (int i = 0; i <= number; i++)
{
//第一層
Vector3 one1 = Vector3.Lerp(startPos, threeCenterPosArr[0], i / number);
Vector3 one2 = Vector3.Lerp(threeCenterPosArr[0], threeCenterPosArr[1], i / number);
Vector3 one3 = Vector3.Lerp(threeCenterPosArr[1], threeCenterPosArr[2], i / number);
Vector3 one4 = Vector3.Lerp(threeCenterPosArr[2], endPos, i / number);
//第二層
Vector3 two1 = Vector3.Lerp(one1, one2, i / number);
Vector3 two2 = Vector3.Lerp(one2, one3, i / number);
Vector3 two3 = Vector3.Lerp(one3, one4, i / number);
//第三層
Vector3 three1 = Vector3.Lerp(two1, two2, i / number);
Vector3 three2 = Vector3.Lerp(two2, two3, i / number);
//目標層
Vector3 targetPos = Vector3.Lerp(three1, three2, i / number);
//將目標層放入我們的路徑點中
targetPosArr[i] = targetPos;
}
return targetPosArr;
}
}