定义
贝塞尔曲线(Bezier curve),又称贝兹曲线或贝济埃曲线,是应用于二维图形应用程序的数学曲线。一般的矢量图形软件通过它来精确画出曲线,贝兹曲线由线段与节点组成,节点是可拖动的支点,线段像可伸缩的皮筋。
首先是一阶贝塞尔曲线公式,如下:
B(t)=P0+(P1−P0)t=(1−t)P0+tP1, t∈[0,1]
二阶公式
B(t)=(1−t)2P0+2t(1−t)P1+t2P2, t∈[0,1]
三阶公式
B(t)=(1−t)3P0+3t(1−t)2P1+3t2(1−t)P2+t3P3, t∈[0,1]
实现
推导细节的话网上有很多详细的教程,这里只作应用
首先我们来看二阶公式,B(t)=(1−t)2P0+2t(1−t)P1+t2P2, t∈[0,1]
假如我们在untiy中想得出一个曲线应该怎么做?
这里我们可以尝试一下
首先最基础的我们应该获得两个坐标点,分别是起点坐标和终点坐标,其次,我们通过调节t的值获得对应的曲线坐标
对应二阶三阶公式代码
public static class BezierTool
{
public static Vector3 GetBezier(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float t)
{
Mathf.Clamp(t, 0, 1);
float x1 = (1 - t) * (1 - t) * (1 - t);
float x2 = 3 * t * (1 - t) * (1 - t);
float x3 = 3 * t * t * (1 - t);
float x4 = t * t * t;
return p0 * x1 + p1 * x2 + p2 * x3 + p3 * x4;
}
/// <summary>
/// 起点,中间点,终点
/// </summary>
/// <param name="p0">起点</param>
/// <param name="p1">中间点</param>
/// <param name="p2">终点</param>
/// <param name="t"></param>
/// <returns></returns>
public static Vector3 GetBezier(Vector3 p0, Vector3 p1, Vector3 p2, float t)
{
float x1 = (1 - t) * (1 - t);
float x2 = 2 * t * (1 - t);
float x3 = t * t;
return p0 * x1 + p1 * x2 + p2 * x3;
}
}
测试运行代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BezierMove : MonoBehaviour
{
public Transform originPoint;
public Transform destinationPoint;
public Transform controlPoint;
float rate;
public float bezierNumber;
List<Vector3> path;
int index;
public float speed = 5;
public bool isStart = false;
private void Start()
{
path = new List<Vector3>();
for (var i = 1; i < bezierNumber; i++)
{
float temp = 1 / bezierNumber;
rate += temp;
rate = Mathf.Clamp(rate, 0, 1f);
Vector3 pathPoint = BezierTool.GetBezier(originPoint.position, controlPoint.position, destinationPoint.position, rate);
path.Add(pathPoint);
}
foreach (var item in path)
{
print(item);
}
index = 0;
}
private void Update()
{
if (!isStart)
{
return;
}
if (index < path.Count)
{
transform.position = Vector3.MoveTowards(transform.position, path[index], Time.deltaTime * speed);
if (Vector3.Distance(transform.position, path[index]) <= 0.1f)
{
index++;
}
}
}
}