c# - 如何更新 Unity GameObject 以沿样条曲线移动?

标签 c# unity3d interpolation gameobject catmull-rom-curve

下午好

我正在尝试在 Unity 中实现一个游戏对象,它在给定 8 个受限随机值的情况下沿着 Cubic CatMull-Rom Spline 移动。我已经实现了一个函数 ComputePointOnCatmullRomCurve,它返回三次 Catmull-Rom 曲线上的一个点(给定一个从 0 到 1 的标量“u”和指示用于插值的 4 个点的 segment_number)。

我在实现更新功能以允许游戏对象平稳移动时遇到问题。我目前在每次更新时都调用 ComputePointOnCatmullRomCurve 并且每次都递增 segment_number。然后将 GameObjects 位置设置为函数的结果。

然而,这会导致游戏对象移动得非常快。我相信我的更新函数不正确,但我不确定如何根据插值函数输出的点移动游戏对象。

如果有人能够向我解释我做错了什么,或者提供示例或示例链接,那将非常有帮助!

计算曲线上点的函数:

Vector3 ComputePointOnCatmullRomCurve(float u, int segmentNumber)
{
    // TODO - compute and return a point as a Vector3       
    // Points on segment number 0 start at controlPoints[0] and end at controlPoints[1]
    // Points on segment number 1 start at controlPoints[1] and end at controlPoints[2]
    //       etc...

    Vector3 point = new Vector3();

    float c0 = ((-u + 2f) * u - 1f) * u * 0.5f;
    float c1 = (((3f * u - 5f) * u) * u + 2f) * 0.5f;
    float c2 = ((-3f * u + 4f) * u + 1f) * u * 0.5f;
    float c3 = ((u - 1f) * u * u) * 0.5f;

    Vector3 p0 = controlPoints[(segmentNumber - 1) % NumberOfPoints];
    Vector3 p1 = controlPoints[segmentNumber % NumberOfPoints];
    Vector3 p2 = controlPoints[(segmentNumber + 1) % NumberOfPoints];
    Vector3 p3 = controlPoints[(segmentNumber + 2) % NumberOfPoints];

    point.x = (p0.x * c0) + (p1.x * c1) + (p2.x * c2) + (p3.x * c3);
    point.y = (p0.y * c0) + (p1.y * c1) + (p2.y * c2) + (p3.y * c3);
    point.x = (p0.z * c0) + (p1.z * c1) + (p2.z * c2) + (p3.z * c3);

    return point;
}

更新函数:

void Update () {
    // TODO - use time to determine values for u and segment_number in this function call
    // 0.5 Can be used as u
    time += DT;

    segCounter++;

    Vector3 temp = ComputePointOnCatmullRomCurve(time, segCounter);
    transform.position = temp;
}

变量:

const int NumberOfPoints = 8;
Vector3[] controlPoints;

const int MinX = -5;
const int MinY = -5;
const int MinZ = 0;

const int MaxX = 5;
const int MaxY = 5;
const int MaxZ = 5;

float time = 0;
const float DT = 0.01f;
public static int segCounter = 0;

谢谢!

马特

最佳答案

您在更新功能中犯了 2 个错误。

第一个错误:

您在每一帧递增当前片段的索引 (segmentNumber)。我想这应该只在对象完成它沿着前一个样条线段行进时完成。

提示:

对于由多个补丁定义的样条曲线,我通常在 [0,n] 范围内表示时间 (u),其中 n 是定义曲线的段数。通过这种方式,您可以检索当前补丁的索引 (segmentNumber),只需从参数中提取整数部分即可。像这样的东西:

int segmentNumber =  Mathf.FloorToInt(u);
float segmentU = u - segmentNumber;

第二个错误

我不知道你的 DT 变量是什么,但除非你在其他地方按帧增量时间缩放它,否则你必须这样做。基本上你可以这样增加时间:

time += Time.deltaTime * speedAlongCurve;

希望对你有帮助。

关于c# - 如何更新 Unity GameObject 以沿样条曲线移动?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26724267/

相关文章:

c# - 如何在 Dapper 中使用 Char 和 VarBinary?

c# - CS0103 : The name 'CType' does not exist in the current context

interpolation - 如何在两组不规则数据之间插值?

python - 使用 scipy.interpolate 具有固定起点和终点的平滑样条近似

scipy - 无法解决导入错误 : cannot import name 'spline' from 'scipy.interpolate'

c# - 在 HttpContext.Cache 中搜索时使用通配符

c# - 按钮单击打开 richTextBox 并显示读取文件

c# - AggressiveInlining 不存在

c# - 在没有 bool 条件的情况下在 Update() 中调用一次

c# - 在现代Unity3D中捏和其他多指手势?