使用Unity画一条平滑曲线(贝塞尔曲线)

转载自 https://blog.csdn.net/xiexian1204/article/details/49592765
在这里插入图片描述
从图中可以看出,只有四个点是保持不变的,分别是P0,P1,P2,P3,这四个点两两相连得到三个线段
(1)在上四点构成的三个线段中,p0-p1上有到一个点,p1-p2上有到一个点,p2-p3上有到一个点,这三个点分别这在上三个线段做差值运算。现在以上三个点分别取名为A1,A2,A3,这三点两两相连得到绿色线
(2)继续观察可看出,上面得到的三个点构成二个线段,A1-A2上得到一点,A2-A2上有一个点。这两点分别在这二个线段上做差值运算,现将这两点分别为B1,B2。这两点相连得到蓝色线
(3)再观察蓝色线上可看出,有一点在这做差值运算,最终轨迹画成曲线。

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


//简单来说,贝塞尔曲线就是对多个线段同时做差值
public class DrawLine : MonoBehaviour
{
    
    //我们让其运动的物体
    public GameObject ball;
    //我们实现创建好的几个点,这里需要实现定义五个点
    public List<Transform> gameOjbet_tran = new List<Transform>();
    //小球的运动点,在Init中计算
    private List<Vector3> point = new List<Vector3>();
    //
    public float speed;
    //临时变量
    int i = 0;
    //计算出指定个点,将他们练成一条直线,使其开起来像是曲线
    void GetPathPoints()
    {
        point = new List<Vector3>();
        float pointNumber = 50;
        for (int i = 0; i <= (int)pointNumber; i++)
        {
            //Debug.Log(i / pointNumber);//他的值从0 - 1
            //一
            Vector3 pos1 = Vector3.Lerp(gameOjbet_tran[0].position, gameOjbet_tran[1].position, i / pointNumber);
            Vector3 pos2 = Vector3.Lerp(gameOjbet_tran[1].position, gameOjbet_tran[2].position, i / pointNumber);
            Vector3 pos3 = Vector3.Lerp(gameOjbet_tran[2].position, gameOjbet_tran[3].position, i / pointNumber);
            Vector3 pos4 = Vector3.Lerp(gameOjbet_tran[3].position, gameOjbet_tran[4].position, i / pointNumber);
            Vector3 pos5 = Vector3.Lerp(gameOjbet_tran[4].position, gameOjbet_tran[5].position, i / pointNumber);
            Vector3 pos6 = Vector3.Lerp(gameOjbet_tran[5].position, gameOjbet_tran[6].position, i / pointNumber);
            //二
            var pos1_0 = Vector3.Lerp(pos1, pos2, i / pointNumber);
            var pos1_1 = Vector3.Lerp(pos2, pos3, i / pointNumber);
            var pos1_2 = Vector3.Lerp(pos3, pos4, i / pointNumber);
            var pos1_3 = Vector3.Lerp(pos4, pos5, i / pointNumber);
            var pos1_4 = Vector3.Lerp(pos5, pos6, i / pointNumber);
            //三
            var pos2_0 = Vector3.Lerp(pos1_0, pos1_1, i / pointNumber);
            var pos2_1 = Vector3.Lerp(pos1_1, pos1_2, i / pointNumber);
            var pos2_2 = Vector3.Lerp(pos1_2, pos1_3, i / pointNumber);
            var pos2_3 = Vector3.Lerp(pos1_3, pos1_4, i / pointNumber);
            //四

            var pos3_0 = Vector3.Lerp(pos2_0, pos2_1, i / pointNumber) ;
            var pos3_1 = Vector3.Lerp(pos2_1, pos2_2, i / pointNumber) ;
            var pos3_2 = Vector3.Lerp(pos2_2, pos2_3, i / pointNumber);
            //五
            var pos4_1 = Vector3.Lerp(pos3_0, pos3_1, i / pointNumber);
            var pos4_2 = Vector3.Lerp(pos3_1, pos3_2, i / pointNumber);

            Vector3 find = Vector3.Lerp(pos4_1, pos4_2, i / pointNumber);
            point.Add(find);
        }
    }
    //画线
    void OnDrawGizmos()
    {
        GetPathPoints();
        Gizmos.color = Color.yellow;
        for (int i = 0; i < point.Count - 1; i++)
        {
            Gizmos.DrawLine(point[i], point[i + 1]);
        }
    }
    //------------------------------------------------------------------------------   
    //使小球做曲线运动
    //这里不能直接在for里以Point使用差值运算,看不到小球运算效果
    //定义一个计时器,在相隔时间内进行一次差值运算。
    void Awake()
    {
        GetPathPoints();
        //在物体身上绑定一个空物体当该物体的爸爸
        ball.transform.parent.position = point[0];
    }
    //
    void Update()
    {
       //物体沿曲线行进旋转
        Vector2 direction = point[i] - transform.position;
        float angle = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg;
        //print(angle);
        transform.rotation =Quaternion.Lerp(transform.rotation, Quaternion.AngleAxis(angle, Vector3.forward),Time.deltaTime*5);
        ball.transform.parent.Translate(direction.normalized * Time.deltaTime * speed);

        //ball.transform.parent.position = point[i];
        if (Vector3.Distance(transform.parent.position, point[i])<5f)
        {
            i++;
            //在终点回到原点
            i %= point.Count;//比如 i=20,count也是20,那就回到point[0]的点也就是原点,然后继续循环
        }

        
    }

}


  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值