Unity中使用贝塞尔算法实现曲线运动

简单的小球沿贝塞尔曲线运动,适合场景漫游使用

贝塞尔曲线:(贝塞尔曲线的基本想法部分摘自http://blog.csdn.net/u010019717/article/details/47684223 。仅供学习,知识分享。如有侵权,联系删除。)

贝塞尔曲线是最基本的曲线,一般用在计算机 图形学和 图像处理。贝塞尔曲线可以用来创建平滑的曲线的道路、 弯曲的路径就像 祖玛游戏、 弯曲型的河流等。

        一条贝塞尔曲线是由一组定义的控制点 P0到 Pn,在 n 调用它的顺序 (n = 1 为线性,2 为二次,等.)。第一个和最后一个控制点总是具有终结点的曲线;然而,中间两个控制点 (如果有的话) 一般不会位于曲线上 。

贝塞尔曲线包含两个控制点即 n = 2 称为线性的贝塞尔曲线

贝塞尔曲线包含三个控制点即 n = 3 称为二次贝塞尔曲线

贝塞尔曲线包含四个控制点即 n = 4,所以称为三次贝塞尔曲线。

............

以上都是复制,想看具体图解,我想有很多帖子,接下来废话不多说,直接上代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BezierDrawLine : MonoBehaviour {

    public List wayPoint = new List();   //路点信息(首尾表示起点和终点,中间为相对n阶偏移点)
    public int pointCount = 100;     //曲线上点的个数
    private List linePointList;
    [Range(0, 1)]
    public float _time = 0.01f;        //两点间的运动间隔
    public Transform player;           //运动物体
    public Transform targetTransform;  //Play目标物体
    private bool isMove = false;
    private float  _curTimer = 0.0f;   //计时
    private int lineItem = 1;          //目标索引


    void Awake() {
        //Init();
    }
	// Use this for initialization
	void Start () {
		
	}
	
	// Update is called once per frame
	void Update () {
        if (!isMove) return;
        _curTimer += Time.deltaTime;
        if (_curTimer > _time)
        {
            _curTimer = 0;
            if (targetTransform)
                player.LookAt(targetTransform);
            else
                player.LookAt(linePointList[lineItem]);
            player.localPosition = Vector3.Lerp(linePointList[lineItem - 1], linePointList[lineItem], 1f);
            lineItem++;
            if (lineItem >= linePointList.Count)
                lineItem = 1;
        }
	}
    // 线性
    Vector3 Bezier(Vector3 p0, Vector3 p1, float t)
    {
        return (1 - t) * p0 + t * p1;
    }
    // 二阶曲线
    Vector3 Bezier(Vector3 p0, Vector3 p1, Vector3 p2, float t)
    {
        Vector3 p0p1 = (1 - t) * p0 + t * p1;
        Vector3 p1p2 = (1 - t) * p1 + t * p2;
        Vector3 result = (1 - t) * p0p1 + t * p1p2;
        return result;
    }
    // 三阶曲线
    Vector3 Bezier(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float t)
    {
        Vector3 result;
        Vector3 p0p1 = (1 - t) * p0 + t * p1;
        Vector3 p1p2 = (1 - t) * p1 + t * p2;
        Vector3 p2p3 = (1 - t) * p2 + t * p3;
        Vector3 p0p1p2 = (1 - t) * p0p1 + t * p1p2;
        Vector3 p1p2p3 = (1 - t) * p1p2 + t * p2p3;
        result = (1 - t) * p0p1p2 + t * p1p2p3;
        return result;
    }

    // n阶曲线,递归实现
    public Vector3 Bezier(float t, List p)
    {
        if (p.Count < 2)
            return p[0];
        List newp = new List();
        for (int i = 0; i < p.Count - 1; i++)
        {
            Debug.DrawLine(p[i], p[i + 1],Color.yellow);
            Vector3 p0p1 = (1 - t) * p[i] + t * p[i + 1];
            newp.Add(p0p1);
        }
        return Bezier(t, newp);
    }
    // transform转换为vector3,在调用参数为List的Bezier函数
    public Vector3 Bezier(float t, List p)
    {
        if (p.Count < 2)
            return p[0].position;
        List newp = new List();
        for (int i = 0; i < p.Count; i++)
        {
            newp.Add(p[i].position);
        }
        //return Bezier(t, newp);
        return MyBezier(t, newp);
    }
    //画出弧线
    public Vector3 MyBezier(float t, List p) {
        if (p.Count < 2)
            return p[0];
        List newp = new List();
        for (int i = 0; i < p.Count - 1; i++)
        {
            //Debug.DrawLine(p[i], p[i + 1], Color.yellow);
            Vector3 p0p1 = (1 - t) * p[i] + t * p[i + 1];
            newp.Add(p0p1);
        }
        return MyBezier(t, newp);
    }

    void Init() {
        linePointList = new List();
        for (int i = 0; i < pointCount; i++)
        {
            var point = Bezier(i / (float)pointCount, wayPoint);
            linePointList.Add(point);
        }
        if (linePointList.Count == pointCount)
            isMove = true;
        //Debug.LogError("isMove == " + isMove);
    }
    //在scene视图显示
    public void OnDrawGizmos()
    {
        Init();
        Gizmos.color = Color.yellow;
        //Gizmos.DrawLine()
        for (int i = 0; i < linePointList.Count - 1; i++)
        {
           //var point_1 = Bezier(i/(float)pointCount, wayPoint);
           //var point_2 = Bezier((i+1) / (float)pointCount, wayPoint);
           //两种划线方式皆可
           //Gizmos.DrawLine(point_1, point_2);
            Debug.DrawLine(linePointList[i], linePointList[i + 1], Color.yellow);
        }
      
    }

}

当然这几乎也是看博客来的,稍稍总结了一下:

OnDrowGizoms()这个方法是会在scene检视面板显示,划线主要是用DrawLine();

Update()中主要是小球沿曲线运动,有了路径还是很好写的

再给你们配一张参数配置:

Unity中使用贝塞尔算法实现曲线运动_第1张图片

 

然后.....Over,哦,欢迎吐槽!

你可能感兴趣的:(unity3D)