1. 通俗來說貝塞爾曲線
在游戲開發(fā)中粪薛,經(jīng)常會(huì)用到拋物線悴了,例如導(dǎo)彈拋物線飛行,用貝塞爾曲線很容易實(shí)現(xiàn)违寿。通俗來講湃交,貝塞爾曲線就是通過三個(gè)點(diǎn),產(chǎn)生一條曲線藤巢,通過一個(gè)變量 t
搞莺,可以取到曲線上的某一個(gè)點(diǎn)的位置,這里的 t
取值是從0.0~1.0
之間掂咒。例如 t
取0.5
才沧,就是取曲線相對(duì)來說中間
的位置點(diǎn)。我覺得這里的 0.0~1.0
可以當(dāng)作一個(gè)百分比
來用绍刮。
2. 曲線函數(shù)
/// <summary>
/// 返回曲線在某一時(shí)間t上的點(diǎn)
/// </summary>
/// <param name="_point0">起始點(diǎn)</param>
/// <param name="_point1">中間點(diǎn)</param>
/// <param name="_point2">終止點(diǎn)</param>
/// <param name="t">當(dāng)前時(shí)間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;
}
例如一個(gè)炮彈從A點(diǎn)要打到B點(diǎn)温圆,在A和B的上方使用一個(gè)點(diǎn)作為中間點(diǎn),就可以拉出一條曲線來孩革,然后通過時(shí)間增量t捌木,在Update中不斷取這條曲線上的點(diǎn),賦予炮彈嫉戚,就可以讓炮彈按拋物線飛行刨裆。
3. 一個(gè)大概的應(yīng)用
using UnityEngine;
using System.Collections;
public class CurveTest : MonoBehaviour
{
public Transform fromPoint; // 起始點(diǎn)
public Transform middlePoint; // 中間點(diǎn)
public Transform endPoint; // 終止點(diǎn)
public Transform moveObj; // 要移動(dòng)的物體
private float ticker = 0.0f;
private float attackTime = 2.0f; // 假設(shè)要用2秒飛到目標(biāo)點(diǎn)
/// <summary>
/// 返回曲線在某一時(shí)間t上的點(diǎn)
/// </summary>
/// <param name="_p0">起始點(diǎn)</param>
/// <param name="_p1">中間點(diǎn)</param>
/// <param name="_p2">終止點(diǎn)</param>
/// <param name="t">當(dāng)前時(shí)間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; // 這里是計(jì)算當(dāng)前已用時(shí)間占計(jì)劃用時(shí)間的百分比,當(dāng)作增量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)
{
// 到達(dá)目標(biāo)點(diǎn)
}
}
}
4. 維基百科上對(duì)于貝塞爾曲線的解釋
圖片來自維基百科