曲線在unity下如何繪製?
類似繪製圓,是用一段一段的線段拼接來模擬的,這邊也是類似,可以用一段一段的線段來模擬曲線。
既然要模擬,那我們也得知道貝塞爾曲線的公式才行。
一般用的比較多的就是3次貝塞爾曲線,該曲線由起點p1,p1的控制點c1,終點p2,p2的控制點c2組成。
公式為:p = p1*(1-t)3 + 3*c1*t*(1-t)2 + 3*c2*t2*(1-t) + p2*t3,t的範圍[0, 1]
下面是unity下的一個貝塞爾編輯工具
public class MyBezierPath2dEdit : MonoBehaviour { public string m_ControlInObjectName = "In"; //作為曲線結束時, c2控制點 public string m_ControlOutObjectName = "Out"; //作為曲線啟示點時, c1控制點 public Color m_ControlInColor = Color.red; //c2控制點連線顏色 public Color m_ControlOutColor = Color.blue; //c1點連線顏色 public Color m_PathColor = Color.yellow; //路徑繪製顏色 [Range(1, 60)] public int m_Steps = 30; //曲線用多少個直線來模擬 public bool m_LoopPath = false; //曲線是否首尾連線 private void OnDrawGizmos() { var mainPoints = new List<Vector2>(); var In = new List<Vector2>(); var Out = new List<Vector2>(); bool isAddRectTransform = null != GetComponent<RectTransform>(); foreach (Transform child in transform) { mainPoints.Add(child.transform.position); foreach (Transform child2 in child.transform) { if (child2.name == m_ControlInObjectName) In.Add(child2.transform.position); if (child2.name == m_ControlOutObjectName) Out.Add(child2.transform.position); } //如果沒有定義的點,則補充上去 if (In.Count < mainPoints.Count) { GameObject go = new GameObject(m_ControlInObjectName); if (isAddRectTransform) go.AddComponent<RectTransform>(); go.transform.SetParent(child.transform, false); In.Add(go.transform.position); } if (Out.Count < mainPoints.Count) { GameObject go = new GameObject(m_ControlOutObjectName); if (isAddRectTransform) go.AddComponent<RectTransform>(); go.transform.SetParent(child.transform, false); Out.Add(go.transform.position); } } //曲線控制線 for (int i = 0; i < mainPoints.Count; i++) { Gizmos.color = m_ControlInColor; Gizmos.DrawLine(mainPoints[i], In[i]); Gizmos.color = m_ControlOutColor; Gizmos.DrawLine(mainPoints[i], Out[i]); } Gizmos.color = m_PathColor; if (In.Count >= mainPoints.Count && Out.Count >= mainPoints.Count) { int mainPtCnt = mainPoints.Count; if (!m_LoopPath) mainPtCnt--; for (int i = 0; i < mainPtCnt; i++) { int i2 = (i + 1) % mainPoints.Count; Vector3 P2 = new Vector3(0, 0, 0); float step = 1.0f / m_Steps; if (step > 0.01f) { for (float t = 0; t < 1 + step; t += step) { Vector3 P1 = P2; P2 = CalcBezierPathPoint(mainPoints[i], Out[i], In[i2], mainPoints[i2], t); if (t > 0) { Gizmos.DrawLine(P1, P2); } } } } } } private Vector3 CalcBezierPathPoint(Vector3 P0, Vector3 C0, Vector3 C1, Vector3 P1, float t) { float temp = 1 - t; Vector2 result = temp * temp * temp * P0 + 3 * temp * temp * t * C0 + 3 * temp * t * t * C1 + t * t * t * P1; return result; } }