Unity實現Bezier曲線的移動(三點之間的Bezier曲線的移動)


直接上代碼:

BezierUtils類獲得三點之間的所有可移動的位置:

using UnityEngine;

public class BezierUtils
{
    /// <summary>
    /// 根據T值,計算貝塞爾曲線上面相對應的點
    /// </summary>
    /// <param name="t"></param>T值
    /// <param name="p0"></param>起始點
    /// <param name="p1"></param>控制點
    /// <param name="p2"></param>目標點
    /// <returns></returns>根據T值計算出來的貝賽爾曲線點
    private static Vector3 CalculateCubicBezierPoint(float t, Vector3 p0, Vector3 p1, Vector3 p2)
    {
        float u = 1 - t;
        float tt = t * t;
        float uu = u * u;

        Vector3 p = uu * p0;
        p += 2 * u * t * p1;
        p += tt * p2;

        return p;
    }

    /// <summary>
    /// 獲取存儲貝塞爾曲線點的數組
    /// </summary>
    /// <param name="startPoint"></param>起始點
    /// <param name="controlPoint"></param>控制點
    /// <param name="endPoint"></param>目標點
    /// <param name="segmentNum"></param>采樣點的數量
    /// <returns></returns>存儲貝塞爾曲線點的數組
    public static Vector3[] GetBeizerList(Vector3 startPoint, Vector3 controlPoint, Vector3 endPoint, int segmentNum)
    {
        Vector3[] path = new Vector3[segmentNum];
        for (int i = 1; i <= segmentNum; i++)
        {
            float t = i / (float)segmentNum;
            Vector3 pixel = CalculateCubicBezierPoint(t, startPoint,
                controlPoint, endPoint);
            path[i - 1] = pixel;
        }
        return path;

    }

}

BezierMove類讓物體在Bezier曲線上的所有點之間移動:

using UnityEngine;
using System.Collections;
using UnityEngine.UI;

/// <summary>
/// 移動完成之后的回調
/// </summary>
public delegate void BezierMoveCompleteDel();
public class BezierMove : MonoBehaviour
{

    /// <summary>
    /// 貝賽爾曲線的路徑點的數量,數量越多獲得的曲線越完美,但是消耗也就越大
    /// </summary>
    private int _segmentNum = 100;
   

    /// <summary>
    /// 獲得貝賽爾曲線所有的路徑點
    /// </summary>
    private Vector3[] _allposArry;

    /// <summary>
    /// 移動的速度
    /// </summary>
    private float _speed = 10;
    /// <summary>
    /// 所有的路徑點的索引值
    /// </summary>
    private int _index = 0;

    /// <summary>
    /// 需要移動的目標
    /// </summary>
    private  Transform _moveTargte;

    /// <summary>
    /// 是否完成移動
    /// </summary>
    private bool _isMoveComplete = false;
    /// <summary>
    ///  初始化貝賽爾曲線所有的路徑點
    /// </summary>
    /// <param name="startPos">開始移動的位置</param>
    /// <param name="controlPos">中間點的位置,目的是改變物體移動的曲線弧度</param>
    /// <param name="endPos">最終移動的位置</param>
    /// <param name="moveTarget">需要移動的目標物體</param>
    /// <param name="moveSpeed">移動速度</param>
    /// <param name="segmentNum">三點之間Bezier曲線上所有點的數量</param>
    public void Init(Vector3 startPos, Vector3 controlPos, Vector3 endPos,Transform moveTarget,float moveSpeed,int segmentNum=100)
    {
        _moveTargte = moveTarget;
        _speed = moveSpeed;
        _allposArry = new Vector3[segmentNum];
        _allposArry = BezierUtils.GetBeizerList(startPos, controlPos, endPos, _segmentNum);
        _isMoveComplete = false;
    }

    /// <summary>
    ///  移動
    /// </summary>
    /// <param name="moveComplete">移動完成的回調</param>
    public void Move(BezierMoveCompleteDel moveComplete=null)
    {
        if (_allposArry == null|| _allposArry.Length==0)
        {
            Debug.LogError("沒有初始化貝賽爾曲線的所有的路徑點");
            return;
        }
        if(!_isMoveComplete)
        {
            if (Vector3.Distance(_moveTargte.position, _allposArry[_index]) <= 0.1f)
            {
                _index++;
                if (_index > _segmentNum - 1)
                {
                    _index = _segmentNum - 1;
                    if (moveComplete != null)
                    {
                        moveComplete();

                    }
                    _isMoveComplete = true;
                }
            }
            else
            {
                _moveTargte.position = Vector3.Slerp(_moveTargte.position, _allposArry[_index], _speed * Time.deltaTime);
            }
        }
       
    }
}

 

 

testBezier測試腳本:

using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using Spine;
using Spine.Unity;
using System;
using Global;
using Kernal;
namespace Controll
{
    public class testBezier : MonoBehaviour
    {
        int _segmentNum = 100;

        public Transform StartPos;
        public Transform ControlPos;
        public Transform EndPos;

        private Vector3[] posArry;

        public float Speed = 10;
        private int _index = 0;

        public Transform Targte;
        [SerializeField]
        private BezierMove _bezierMove;
        private void Start()
        {
            _bezierMove.Init(StartPos.position,ControlPos.position,EndPos.position,Targte, Speed, _segmentNum);
        }
        private void Update()
        {
            _bezierMove.Move(ONComplete);
        }

        private void ONComplete()
        {
            Debug.Log("移動完畢");
        }
    }
}

unity編輯器下的環境:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM