貝塞爾曲線,簡單就是對點之間連續進行插值,最后剩下兩個點之后的計算結果
即如點A,B,C,D,E,對這些點進行兩兩插值,如A1=AB,即A1是對A和B進行插值后的結果
A1=AB,B1=BC,C1=CD,D1=DE
A2=A1B1,B2=B1C1,C2=C1D1
A3=A2B2,B3=B2C2
Result=A3B3
這里貼上我認為的比較好的一個仁兄的博客地址:https://blog.csdn.net/qq_35539447/article/details/80486247
下面是我的代碼
using JetBrains.Annotations; using System.Collections; using System.Collections.Generic; using UnityEngine; public class Bezier : MonoBehaviour { /// <summary> /// 三個控制點的貝塞爾曲線 /// </summary> /// <param name="handles"></param> /// <param name="vertexCount"></param> /// <returns>返回貝塞爾曲線路徑點表</returns> public static List<Vector3> BezierCurveWithThree(Transform[] handles,int vertexCount) { List<Vector3> pointList = new List<Vector3>(); for (float ratio = 0; ratio <= 1; ratio += 1.0f / vertexCount) { Vector3 tangentLineVertex1 = Vector3.Lerp(handles[0].position, handles[1].position, ratio); Vector3 tangentLineVertex2 = Vector3.Lerp(handles[1].position, handles[2].position, ratio); Vector3 bezierPoint = Vector3.Lerp(tangentLineVertex1, tangentLineVertex2, ratio); pointList.Add(bezierPoint); } pointList.Add(handles[2].position); return pointList; } /// <summary> /// 超過三個控制點的貝塞爾曲線 /// </summary> /// <param name="handlesPositions"></param> /// <param name="vertexCount"></param> public static List<Vector3> BezierCurveWithUnlimitPoints(Transform[] handlesPositions,int vertexCount) { List<Vector3> pointList = new List<Vector3>(); for (float ratio = 0; ratio <= 1; ratio += 1.0f / vertexCount) { pointList.Add(UnlimitBezierCurve(handlesPositions, ratio)); } pointList.Add(handlesPositions[handlesPositions.Length - 1].position); return pointList; } public static Vector3 UnlimitBezierCurve(Transform[] trans, float t) { Vector3[] temp = new Vector3[trans.Length]; for (int i = 0; i < temp.Length; i++) { temp[i] = trans[i].position; } int n = temp.Length - 1; for (int i = 0; i < n; i++) { for (int j = 0; j < n - i; j++) { temp[j] = Vector3.Lerp(temp[j], temp[j + 1], t); } } return temp[0]; } }
貝塞爾曲線動態組件代碼
using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using UnityEngine; public class BezierController : MonoBehaviour { public bool isRunning; public bool isShowGizmos; public bool isShowLineRenderer; public bool isShowFixedPoints; [Header("控制手柄")] public Transform[] handles; Vector3[] handlesOriginalPoint;//控制帶你的原始位置 public int vertexCount; List<Vector3> pointList = new List<Vector3>(); [Header("固定點距離點集合")] public List<Vector3> fixedSpacePoints = new List<Vector3>(); public float fixedSpace; [Header("線渲染工具")] public LineRenderer lineRenderer; private void Start() { handlesOriginalPoint = new Vector3[handles.Length]; for(int i = 0; i < handles.Length; i++) { handlesOriginalPoint[i] = handles[i].position; } Running(); } private void Update() { if (CheckHandlesMove()&&isRunning) { Running(); } } void Running() { pointList = Bezier.BezierCurveWithUnlimitPoints(handles, vertexCount); fixedSpacePoints = MathTools.GetEqualySpacePoints(pointList, fixedSpace); if (isShowLineRenderer) { lineRenderer.positionCount = pointList.Count; lineRenderer.SetPositions(pointList.ToArray()); } } //獲取路徑點 public List<Vector3> GetPointList() { return Bezier.BezierCurveWithUnlimitPoints(handles, vertexCount); } //獲取固定間隔距離位置 public List<Vector3> GetFixedSpacePoints() { CheckHandlesMove(); List<Vector3> list = Bezier.BezierCurveWithUnlimitPoints(handles, vertexCount); return MathTools.GetEqualySpacePoints(list, fixedSpace); } //控制點是否發生更新: 是否改變了控制點的數量或者控制點是否發生了位移 bool CheckHandlesMove() { bool hasMove = false; if(handlesOriginalPoint==null)handlesOriginalPoint = new Vector3[]{}; if (handlesOriginalPoint.Length != handles.Length) { handlesOriginalPoint = new Vector3[handles.Length]; for (int i = 0; i < handles.Length; i++) { handlesOriginalPoint[i] = handles[i].position; } return true; } for(int i = 0; i < handles.Length; i++) { if(handles[i].position!= handlesOriginalPoint[i]) { hasMove = true; break; } } return hasMove; } private void OnDrawGizmos() { if (isShowGizmos) { if (handles.Length > 3) { #region 無限制頂點數 Gizmos.color = Color.green; for (int i = 0; i < handles.Length - 1; i++) { Gizmos.DrawLine(handles[i].position, handles[i + 1].position); } Gizmos.color = Color.red; Vector3[] temp = new Vector3[handles.Length]; for (int i = 0; i < temp.Length; i++) { temp[i] = handles[i].position; } int n = temp.Length - 1; for (float ratio = 0.5f / vertexCount; ratio < 1; ratio += 1.0f / vertexCount) { for (int i = 0; i < n - 2; i++) { Gizmos.DrawLine(Vector3.Lerp(temp[i], temp[i + 1], ratio), Vector3.Lerp(temp[i + 2], temp[i + 3], ratio)); } } #endregion } else { #region 頂點數為3 Gizmos.color = Color.green; Gizmos.DrawLine(handles[0].position, handles[1].position); Gizmos.color = Color.green; Gizmos.DrawLine(handles[1].position, handles[2].position); Gizmos.color = Color.red; for (float ratio = 0.5f / vertexCount; ratio < 1; ratio += 1.0f / vertexCount) { Gizmos.DrawLine(Vector3.Lerp(handles[0].position, handles[1].position, ratio), Vector3.Lerp(handles[1].position, handles[2].position, ratio)); } #endregion } } if (isShowFixedPoints) { #region 顯示固定距離的點列表 Gizmos.color = Color.green; foreach (Vector3 point in fixedSpacePoints) { Gizmos.DrawSphere(point, 0.3f); } #endregion } } }
上面的MathTool看我的另一個博客文章unity數學工具