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

Math 以恒定速度沿直线段的路径移动,math,line,interpolation,motion,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

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

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);
    }
}
公共类演示
{
公共浮动速度=1;
私人名单点;
私有浮动t;//[0..1]
专用向量3评估(浮点t)
{
//找出我们目前所处的位置
int lastPointIndex=GetLast(t);
int-nextPointIndex=GetNext(t);
//显然,我需要转换参数t
//调整每个分段的单个长度。
浮点段长度=GetLength(lastPointIndex,nextPointIndex);
//但是我该怎么做呢?
返回向量3.Lerp(点[lastPointIndex],点[nextPointIndex],t);
}
公共无效更新()
{
//曲线参数t以恒定速度在0和1之间移动。
t=数学乒乓球(时间*速度,1);
//然后只得到曲线时间的评估位置,但是
//如果点的间距不均匀,则会产生不同的速度。
向量3位置=评估(t);
SetObjectPosition(位置);
}
}
我意识到,为了实现恒定的速度,我需要重新缩放参数t,以考虑每个段的长度,但我似乎无法确切地找出如何调整


我也知道,我可以通过以我想要的速度向下一个点移动来近似路径,并且只有当我靠近或跟踪t时才改变方向,当t移动到下一段时才改变方向,但这似乎有点困难,当我真的知道每个片段的确切长度,并且应该能够精确地插值时。

这其实很简单。首先,为对象定义所需的速度。例如,每秒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);
}
}
公共类演示
{
公共浮动速度=1;
私人名单点;
私有浮动t;//[0..1]
专用向量3评估(浮点t)
{
//找出我们目前所处的位置
int lastPointIndex=GetLast(t);
int-nextPointIndex=GetNext(t);
浮点段长度=GetLength(lastPointIndex,nextPointIndex);
浮动比例因子=分段长度/速度;
//注意,我用scaleFactor除以t,而不是乘法。
//这是因为Lerp总是以[0..1]为间隔
//改为调整曲线参数。
返回向量3.Lerp(点[lastPointIndex],点[nextPointIndex],t/scaleFactor);
}
公共无效更新()
{
//曲线参数t以恒定速度在0和1之间移动。
t=数学乒乓球(时间*速度,1);
//然后只得到曲线时间的评估位置,但是
//如果点的间距不均匀,则会产生不同的速度。
向量3位置=评估(t);
SetObjectPosition(位置);
}
}