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编辑器下的环境:

原文地址:https://www.cnblogs.com/weiqiangwaideshijie/p/10180077.html