沿着直线段的路径以恒定速度移动

时间:2017-11-30 14:40:11

标签: math line interpolation motion

我有一个矢量点列表,它定义了一个对象所遵循的直线段的路径。目前,我进行线性插值以沿着路径动画运动,如下所示:

public class Demo
{
    public float speed = 1;
    private List<Vector3> points;

    private float t; // [0..1]

    private Vector3 Evaluate(float t)
    {
        // Find out in between which points we currently are
        int lastPointIndex = GetLast(t);
        int nextPointIndex = GetNext(t);

        // Obviously, I need to somehow transform parameter t
        // to adjust for the individual length of each segment.

        float segmentLength = GetLength(lastPointIndex, nextPointIndex);

        // But how would I do this?
        return Vector3.Lerp(points[lastPointIndex], points[nextPointIndex], t);
    }

    public void Update()
    {
        // Curve parameter t moves between 0 and 1 at constant speed.
        t = Mathf.PingPong(Time.time * speed, 1);

        // Then just get the evaluated position for the curve time, but
        // this gives variant speed if points are not evenly spaced.
        Vector3 position = Evaluate(t);
        SetObjectPosition(position);
    }
}

我意识到,要实现恒定速度,我需要重新调整参数t以考虑每个段的长度,但我似乎无法确切知道如何。

我也知道,我可以通过以我想要的速度向下一个点移动来近似路径,只改变方向,一旦我靠近或跟踪t并且一旦它移动到方向上就改变方向下一段,但这看起来很糟糕,当我实际知道每个段的确切长度时,应该能够完全插入它。

1 个答案:

答案 0 :(得分:0)

这实际上很安静。首先,为对象定义所需的速度。例如,每秒6个单位。这意味着如果一个线段的长度为6个单位,那么你的对象需要1秒才能从它的开始到结束点。这也意味着如果你的线段长度是这个长度的一半(即3个单位),它将需要0.5秒的物体穿过它。因此,您需要做的是计算所有线段的长度,并将其除以您想要的速度(3/6 = 0.5 = scaleFactor)。然后,不是在0和1之间进行插值,而是在0和1*scaleFactor之间进行插值。然后你的代码变成:

public class Demo
{
public float speed = 1;
private List<Vector3> points;

private float t; // [0..1]

private Vector3 Evaluate(float t)
{
    // Find out in between which points we currently are
    int lastPointIndex = GetLast(t);
    int nextPointIndex = GetNext(t);

    float segmentLength = GetLength(lastPointIndex, nextPointIndex);
    float scaleFactor = segmentLength/speed;

    // note that I divided t by scaleFactor instead of multiplication. 
    // That's because Lerp always takes an interval of [0..1]. So, we
    // adjust the curve parameter instead.
    return Vector3.Lerp(points[lastPointIndex], points[nextPointIndex], t/scaleFactor);
}

public void Update()
{
    // Curve parameter t moves between 0 and 1 at constant speed.
    t = Mathf.PingPong(Time.time * speed, 1);

    // Then just get the evaluated position for the curve time, but
    // this gives variant speed if points are not evenly spaced.
    Vector3 position = Evaluate(t);
    SetObjectPosition(position);
}
}