C#版貝塞爾曲線代碼:包含3點和5點確定曲線

如題,有三個點的曲線(開始點,中間點,結束點)

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;
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章