Unity3D 使用贝塞尔曲线控制物体抛物线移动

1. 通俗来说贝塞尔曲线

在游戏开发中,经常会用到抛物线,例如导弹抛物线飞行,用贝塞尔曲线很容易实现。通俗来讲,贝塞尔曲线就是通过三个点,产生一条曲线,通过一个变量 t,可以取到曲线上的某一个点的位置,这里的 t 取值是从0.0~1.0之间。例如 t0.5,就是取曲线相对来说中间的位置点。我觉得这里的 0.0~1.0可以当作一个百分比来用。

2. 曲线函数

/// 
/// 返回曲线在某一时间t上的点
/// 
/// 起始点
/// 中间点
/// 终止点
/// 当前时间t(0.0~1.0)
/// 
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秒飞到目标点

    /// 
    /// 返回曲线在某一时间t上的点
    /// 
    /// 起始点
    /// 中间点
    /// 终止点
    /// 当前时间t(0.0~1.0)
    /// 
    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

图片来自维基百科

你可能感兴趣的:(Unity3D 使用贝塞尔曲线控制物体抛物线移动)