转载自 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 gameOjbet_tran = new List();
//小球的运动点,在Init中计算
private List point = new List();
//
public float speed;
//临时变量
int i = 0;
//计算出指定个点,将他们练成一条直线,使其开起来像是曲线
void GetPathPoints()
{
point = new List();
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]的点也就是原点,然后继续循环
}
}
}