使用贝塞尔曲线来实现对象在Unity中的飞行是一种常见的方法。这种方法可以用来制作各种平滑的移动路径,比如子弹轨迹、角色运动路径等。下面是介绍两种方法,展示如何在Unity中使用贝塞尔曲线让对象沿着一条路径飞行。
第一种:在update里面动态改变坐标
1.创建贝塞尔曲线
using UnityEngine;
public static class BezierCurve
{
// 二次贝塞尔曲线公式
public static Vector3 GetQuadraticPoint(Vector3 p0, Vector3 p1, Vector3 p2, float t)
{
return Mathf.Pow(1 - t, 2) * p0 + 2 * (1 - t) * t * p1 + Mathf.Pow(t, 2) * p2;
}
// 三次贝塞尔曲线公式
public static Vector3 GetCubicPoint(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float t)
{
return Mathf.Pow(1 - t, 3) * p0 +
3 * Mathf.Pow(1 - t, 2) * t * p1 +
3 * (1 - t) * Mathf.Pow(t, 2) * p2 +
Mathf.Pow(t, 3) * p3;
}
}
2. 飞行脚本
我们编写一个脚本,将对象沿着贝塞尔曲线飞行。我们将允许用户设置起点、中间控制点和终点。
为了更好地调整和可视化贝塞尔曲线,编写一个Gizmos绘制函数,在编辑模式下显示整个曲线:
using UnityEngine;
[ExecuteInEditMode]
public class BezierFly : MonoBehaviour
{
public Transform point0;
public Transform point1;
public Transform point2;
public Transform point3;
public float duration = 5f;
private float timeElapsed;
void Update()
{
if (!Application.isPlaying)
{
return;
}
timeElapsed += Time.deltaTime;
float t = timeElapsed / duration;
if (t > 1)
{
t = 1;
}
if (point3 != null)
{
transform.position = BezierCurve.GetCubicPoint(point0.position, point1.position, point2.position, point3.position, t);
}
else
{
transform.position = BezierCurve.GetQuadraticPoint(point0.position, point1.position, point2.position, t);
}
if (t >= 1)
{
// 结束逻辑
}
}
void OnDrawGizmos()
{
Gizmos.color = Color.green;
DrawBezierCurve(20);
}
private void DrawBezierCurve(int segments)
{
Vector3[] points;
if (point3 != null)
{
points = new Vector3[segments + 1];
for (int i = 0; i <= segments; i++)
{
float t = i / (float)segments;
points[i] = BezierCurve.GetCubicPoint(point0.position, point1.position, point2.position, point3.position, t);
}
}
else
{
points = new Vector3[segments + 1];
for (int i = 0; i <= segments; i++)
{
float t = i / (float)segments;
points[i] = BezierCurve.GetQuadraticPoint(point0.position, point1.position, point2.position, t);
}
}
for (int i = 0; i < segments; i++)
{
Gizmos.DrawLine(points[i], points[i + 1]);
}
}
}
3.使用
a. 将这个脚本 BezierFly 附加到你希望沿曲线飞行的对象上。
b. 创建四个空物体作为贝塞尔曲线的控制点,并将它们的 Transform 分别赋值给 point0, point1, point2, 和可选的 point3。
第二种:结合 DoTween 来做飞行
对上面BezierFly进行微改即可
using UnityEngine;
[ExecuteInEditMode]
public class BezierFly : MonoBehaviour
{
public Transform point0;
public Transform point1;
public Transform point2;
public Transform point3;
public float duration = 5f;
void Start()
{
if (!Application.isPlaying) return;
if (point3 != null)
{
DOVirtual.Float(0, 1, duration, t =>
{
transform.position = BezierCurve.GetCubicPoint(point0.position, point1.position, point2.position, point3.position, t);
}).SetEase(Ease.Linear).OnComplete(OnComplete);
}
else
{
DOVirtual.Float(0, 1, duration, t =>
{
transform.position = BezierCurve.GetQuadraticPoint(point0.position, point1.position, point2.position, t);
}).SetEase(Ease.Linear).OnComplete(OnComplete);
}
}
private void OnComplete()
{
Debug.Log("Animation Complete");
}
void OnDrawGizmos()
{
Gizmos.color = Color.green;
DrawBezierCurve(20);
}
private void DrawBezierCurve(int segments)
{
Vector3[] points;
if (point3 != null)
{
points = new Vector3[segments + 1];
for (int i = 0; i <= segments; i++)
{
float t = i / (float)segments;
points[i] = BezierCurve.GetCubicPoint(point0.position, point1.position, point2.position, point3.position, t);
}
}
else
{
points = new Vector3[segments + 1];
for (int i = 0; i <= segments; i++)
{
float t = i / (float)segments;
points[i] = BezierCurve.GetQuadraticPoint(point0.position, point1.position, point2.position, t);
}
}
for (int i = 0; i < segments; i++)
{
Gizmos.DrawLine(points[i], points[i + 1]);
}
}
}