1. 通俗来说贝塞尔曲线
在游戏开发中,经常会用到抛物线,例如导弹抛物线飞行,用贝塞尔曲线很容易实现。通俗来讲,贝塞尔曲线就是通过三个点,产生一条曲线,通过一个变量 t
,可以取到曲线上的某一个点的位置,这里的 t
取值是从0.0~1.0
之间。例如 t
取0.5
,就是取曲线相对来说中间
的位置点。我觉得这里的 0.0~1.0
可以当作一个百分比
来用。
2. 曲线函数
/// <summary>
/// 返回曲线在某一时间t上的点
/// </summary>
/// <param name="_point0">起始点</param>
/// <param name="_point1">中间点</param>
/// <param name="_point2">终止点</param>
/// <param name="t">当前时间t(0.0~1.0)</param>
/// <returns></returns>
public static Vector3 GetCurvePoint(Vector3 _point0, Vector3 _point1, Vector3 _point2, float t)
{
t = Mathf.Clamp(t, 0.0f, 1.0f);
float x = ((1 - t) * (1 - t)) * _point0.x + 2 * t * (1 - t) * _point1.x + t * t * _point2.x;
float y = ((1 - t) * (1 - t)) * _point0.y + 2 * t * (1 - t) * _point1.y + t * t * _point2.y;
float z = ((1 - t) * (1 - t)) * _point0.z + 2 * t * (1 - t) * _point1.z + t * t * _point2.z;
Vector3 pos = new Vector3(x, y, z);
return pos;
}
例如一个炮弹从A点要打到B点,在A和B的上方使用一个点作为中间点,就可以拉出一条曲线来,然后通过时间增量t,在Update中不断取这条曲线上的点,赋予炮弹,就可以让炮弹按抛物线飞行。
3. 一个大概的应用
using UnityEngine;
using System.Collections;
public class CurveTest : MonoBehaviour
{
public Transform fromPoint; // 起始点
public Transform middlePoint; // 中间点
public Transform endPoint; // 终止点
public Transform moveObj; // 要移动的物体
private float ticker = 0.0f;
private float attackTime = 2.0f; // 假设要用2秒飞到目标点
/// <summary>
/// 返回曲线在某一时间t上的点
/// </summary>
/// <param name="_p0">起始点</param>
/// <param name="_p1">中间点</param>
/// <param name="_p2">终止点</param>
/// <param name="t">当前时间t(0.0~1.0)</param>
/// <returns></returns>
public static Vector3 GetCurvePoint(Vector3 _p0, Vector3 _p1, Vector3 _p2, float t)
{
t = Mathf.Clamp(t, 0.0f, 1.0f);
float x = ((1 - t) * (1 - t)) * _p0.x + 2 * t * (1 - t) * _p1.x + t * t * _p2.x;
float y = ((1 - t) * (1 - t)) * _p0.y + 2 * t * (1 - t) * _p1.y + t * t * _p2.y;
float z = ((1 - t) * (1 - t)) * _p0.z + 2 * t * (1 - t) * _p1.z + t * t * _p2.z;
Vector3 pos = new Vector3(x, y, z);
return pos;
}
private void Update()
{
ticker += Time.deltaTime;
float t = ticker / attackTime; // 这里是计算当前已用时间占计划用时间的百分比,当作增量t
t = Mathf.Clamp(t, 0.0f, 1.0f);
Vector3 p1 = fromPoint.position;
Vector3 p2 = middlePoint.position;
Vector3 p3 = endPoint.position;
Vector3 currPos = GetCurvePoint(p1, p2, p3, timeValue);
moveObj.position = currPos;
if(t == 1.0f)
{
// 到达目标点
}
}
}
4. 维基百科上对于贝塞尔曲线的解释
image
图片来自维基百科