在Unity 5中沿着bezier曲线近似物体的时间和位置

本文关键字:时间 位置 曲线 Unity bezier | 更新日期: 2023-09-27 18:05:34

我目前有一个物体,我正在沿着曲线移动很长的贝塞尔曲线,通过沿着曲线采样几个点,然后使用Unity的MoveTowards以恒定的速度将物体移动到每个点。

在我这样做之前,我想通过计算点之间的距离,然后除以汽车的速度,来估计物体到达我当前正在做的每个点所需的时间。

我得到的值通常是一个或两个小数点后,我注意到的是时间值的变化。Unity是否做了一些我应该考虑的事情,是否有可能得到更准确的结果,至少是1个小数点?

编辑:这里是一些代码,这样你就可以看到我在做什么:

这是内部模拟

    float initialTime = Time.time;
    Debug.Log("Initial time simulation: " + initialTime);
    float distance = 0;
    Vector3 curr = transform.position;
    Vector3 next;
    for (int s = 1; s < steps+1; ++s)
    {
        float segment = (1.0f - (s/ (float)steps)); 
        next = curve.GetPointAt(segment);
        next.y = curr.y; //Only using x and z of bezier curves
        distance += (next - curr).magnitude;
        curr = next;
        float elapsedTime = distance / speed;
        output[s - 1] = new KeyValuePair<float, Vector3>(initialTime+elapsedTime, point);
    }

这是实际模拟的

    int counter = 1;
    Debug.Log("Initial Time Actual: " + Time.time);
    Vector3 toPoint = curve.GetPointAt((float)(steps - counter) / (steps));
    toPoint.y = transform.position.y;
    transform.LookAt(toPoint);
    while (counter <= steps)
    {
        Vector3 newPos = Vector3.MoveTowards(transform.position, toPoint, speed * Time.deltaTime);
        transform.LookAt(newPos);
        transform.position = newPos; 
        if (transform.position == toPoint)
        {
            Debug.Log("CurrTime: " + Time.time + " " + transform.position);
            ++counter;
            toPoint = curve.GetPointAt((float)(steps - counter) / (steps));
            toPoint.y = transform.position.y;
            transform.LookAt(toPoint);
        }
        yield return null;
    }

在Unity 5中沿着bezier曲线近似物体的时间和位置

除非您提供更多细节,否则我只能猜测您在计算每帧移动汽车的距离时没有考虑Time.deltaTime

看,Update()函数在每一帧上执行,但是帧与帧之间的时间不一定是一致的。Time.deltaTime给出了从上一帧到当前一帧之间经过的时间。

你必须这样做,就像Unity文档中建议的那样:

private Vector3[] bezierTargets;
private float speed;
private int currentTarget;
// ...
void Update() {
    // ...
    float step = speed * Time.deltaTime;
    transform.position = Vector3.MoveTowards(transform.position, bezierTargets[currentTarget].position, step);
}