【问题标题】:Moving along a path of straight line segments at constant speed沿直线段的路径匀速移动
【发布时间】:2017-11-30 14:40:10
【问题描述】:

我有一个向量点列表,它定义了一个对象要遵循的直线段路径。目前,我使用线性插值来为沿路径的运动设置动画,如下所示:

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 时才改变方向,并在它移过时改变方向下一段,但这似乎很hacky,当我实际上知道每个段的确切长度并且应该能够准确地插值时。

【问题讨论】:

    标签: math line interpolation motion


    【解决方案1】:

    这实际上很容易。首先,为您的对象定义一个您想要的速度。例如,每秒 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);
    }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-16
      相关资源
      最近更新 更多