【问题标题】:Unity coroutine movement over time is not consistent/accurate?随着时间的推移,Unity协程移动不一致/准确?
【发布时间】:2016-03-18 01:19:34
【问题描述】:

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

这是我的代码的 sn-p:

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 的一致最终值,这正是我所需要的。但是这段代码不会随着时间的推移平稳地移动相机,这不是我想要的。

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

【问题讨论】:

  • 您能否详细说明一下您所说的翻译无法顺利移动相机的意思?
  • @VenkatatAxiomStudios 我的意思是,如果我只是调用 Translate,它不会随着时间的推移移动相机。移动看起来就像相机从 A 点传送到 B 点,希望这是有道理的

标签: unity3d coroutine


【解决方案1】:

结果实际上与预期非常一致。您的代码绝对没有问题,而是因为帧速率不同。

您看到细微差异的原因是因为无法保证两个帧将花费确切的时间来渲染。 看看这一行

elapsedTime += Time.deltaTime;

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

一个部分解决方法可能是改用Time.smoothDeltaTime,它是几帧上 deltaTime 的平滑值。然而,这并不完美。

第二种方法(本身并不完全是一个答案,但我也将这里留给其他人)是使用补间引擎,例如DoTweeniTween。 这些引擎的方法基本上可以满足您的要求。

【讨论】:

  • 啊,我明白了……我以前用过DoTween,我想我可以走那条路。但出于好奇,有没有办法在不使用补间引擎的情况下使其正常工作?
【解决方案2】:
    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 与持续时间进行比较。因此,在最后一次运行中,您移动然后增加并进行比较。因此,不会考虑最后一次增加,您最终会在接近尾声的某个地方结束,但不是在尾声。

【讨论】:

  • 我试过你写的sn-p代码,效果很好!我的相机 yPos 得到了一致的最终值,这正是我所需要的。谢谢你的解释。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-10-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多