unity coroutine 随时间移动是不是consistent/accurate?

Unity coroutine movement over time is not consistent/accurate?

我有一个协同程序,每当玩家到达游戏中的某个点时,它就会向上移动我的相机。我使用了协程,这样相机会随着时间的推移平稳移动。

这是我的代码片段:

private IEnumerator MoveCameraUpCoroutine(Vector3 startPos, Vector3 endPos, float duration)
    {
        float elapsedTime = 0;
        while(elapsedTime < duration)
        {
            transform.position = Vector3.Lerp(startPos, endPos, (elapsedTime/duration));
            elapsedTime += Time.deltaTime;
            yield return null;
        }
    }

public void MoveCameraUp(Vector3 startPos, Vector3 endPos, float duration)
    {
        StartCoroutine(MoveCameraUpCoroutine(startPos, endPos, duration));
    }

在我的控制器脚本中,我只是这样调用协程:

        cam.GetComponent<CameraMovement>().MoveCameraUp(cam.transform.position,
                                                        new Vector3(cam.transform.position.x, cam.transform.position.y + setupLevel.heightOfBlock, cam.transform.position.z),
                                                        0.1f);

这个问题是相机的运动在它应该停止的地方并不总是一致的。我做了一些调试。在第一个 运行 上,镜头移动到 0.7864508 yPos。第二个运行,镜头移到0.7789915 yPos。等等,这是不一致的。

但是当我简单地使用 Translate 而不是我的协程时:

cam.transform.Translate(0, setupLevel.heightOfBlock, 0);

我在 0.7876318 处获得了相机 yPos 的一致最终值,这正是我所需要的。但是这段代码不会随着时间的推移平滑地移动相机,这不是我想要的。

有谁知道如何解决这个协程问题?我不知道,但我认为我的协程代码有问题。任何帮助是极大的赞赏。

结果其实和预想的很吻合。您的代码绝对没有问题,而是因为帧速率不同。

您看到细微差异的原因是无法保证两帧渲染所用的时间完全相同。 看看这一行

elapsedTime += Time.deltaTime;

您在这里所做的是为您的运行时间添加不一致的值。 (即 Time.deltaTime 每帧都不同)。

一个部分修复可能是使用 Time.smoothDeltaTime 代替,它是 deltaTime 在几个帧上的平滑值。然而,这并不完美。

第二种方法(本身不完全是一个答案,但我也将其留给其他人)是使用补间引擎,例如 DoTweenor iTween。 这些引擎的方法基本上可以完成您想要做的事情。

    float elapsedTime = 0;
    float ratio = elapsedTime / duration;
    while(ratio < 1f)
    {
        elapsedTime += Time.deltaTime;
        ratio = elapsedTime / duration;
        transform.position = Vector3.Lerp(startPos, endPos, ratio);      
        yield return null;
    }

使用此设置,您的循环将 运行 直到 ratio 为 1。当 1 时,返回 endPos 并且循环在下一轮退出。

我认为问题在于您将 elapsedTime 与持续时间进行了比较。所以在最后一个 运行 上,你移动然后你增加然后你比较。结果,最后一次增加没有被考虑,你最终接近尾声但不是尾声。