Unity3D - 使用 Time.deltaTime 作为协程的等待时间

Unity3D - Using Time.deltaTime as wait time for a coroutine

TL,DR: 在协程中使用 Time.deltaTime 作为 yield 的等待时间安全吗?

通常为了避免 Update() 内部不必要的逻辑以实现短暂的功能,我会 运行 一个协程。例如,在我的游戏中,我有一个慢速协程,它定期检查 NPC 和玩家之间的距离,如果该距离低于某个阈值,我将 运行 一个更频繁的协程,使用光线投射进行更昂贵的视线测试等等。这似乎比在 Update() 中不断检查所有内容更有效。

我的问题是:使用 Time.deltaTime 作为 yield 的等待时间,从而在协程期间模拟 Update() 是否安全?即 yield return new WaitForSeconds(Time.deltaTime);

由于 deltaTime 不是常量,如果下一帧花费的时间比上一帧长,会发生什么情况 - 协程是否延迟到下一帧,或者是否发生了可怕的事情,比如整个帧都被延迟到协程完成?我很想允许一个安全缓冲区,例如yield return new WaitForSeconds(Time.deltaTime * 1.2f); 但理想情况下,我希望它能够精确地执行每一帧。

is it safe to use Time.deltaTime as the wait time for the yield in a coroutine?

。那不是如何使用 WaitForSeconds 函数。 WaitForSeconds 以秒为单位作为参数,而不是 Time.deltaTime 在每一帧中提供的微小值。

下面是如何使用 WaitForSeconds 函数的示例。

IEnumerator waitFunction1()
{
    Debug.Log("Hello Before Waiting");
    yield return new WaitForSeconds(3); //Will wait for 3 seconds then run the code below
    Debug.Log("Hello After waiting for 3 seconds");
}

至于使用 Time.deltaTime 等待,除了另一个 float 变量之外,您通常在 while 循环中使用它 incrementdecrement until you reach the wanted value.The 使用 Time.deltaTime 的好处是你可以在等待时看到还剩多少等待时间。您可以将其用于倒计时或倒计时。您还将 yield return null; 放在 while 循环中,这样 Unity 将允许其他脚本也 运行 并且您的应用程序不会冻结。下面是如何使用 Time.deltaTime 等待 3 秒的示例。您可以轻松地将其变成倒数计时器。

IEnumerator waitFunction2()
{
    const float waitTime = 3f;
    float counter = 0f;

    Debug.Log("Hello Before Waiting");
    while (counter < waitTime)
    {
        Debug.Log("Current WaitTime: " + counter);
        counter += Time.deltaTime;
        yield return null; //Don't freeze Unity
    }
    Debug.Log("Hello After waiting for 3 seconds");
}

如果你想检查每一帧有WaitForEndOfFrame

如果您不需要特定的等待时间,WaitForSeconds 就没有意义

您也可以yield return www等待它完成

更新,有CustomYieldInstruction和一些继承用于协程,比如WaitUntil

我知道这有点旧,但我今天在寻找相关内容时偶然发现了它。

无论如何,程序员的回答是一个好的开始。使用 Time.detlaTime 不是释放协程控制的好方法。首先,使用空值将使您进入模拟的下一帧。其次,如果您刚完成的帧有点慢(或下一帧有点快)会发生什么情况。请记住,模拟(或游戏)是按帧运行的,就像电影中的帧一样。因此,使用 WaitForSeconds 可以产生一些有趣的效果。例如,如果您请求的时间发生在帧之间,您认为会发生什么?协程将在 请求的时间后重新获得控制权。因此,如果您希望在协程中的每个循环中只执行 WaitForSeconds(Time.deltaTime),那么您很可能会跳过偶尔的帧(有时更多)。

我有一个同事在一个很长的 运行 协同程序中做了一堆 WaitForSeconds,总时间比预期长 5 到 10 秒。请求时间内帧错误的一部分会累加起来,并且与自然界不同​​,在自然界中错误往往会被平均掉,这些错误总是会增加 up。那是因为流逝的时间总是大于或等于请求的时间。

程序员的回答告诉你如何使用Time.deltaTime来获取模拟时间的流逝。我应该警告你,一旦你开始使用 null 以外的东西来释放协程的控制权,Time.deltaTime 可能会停止为你工作。

如果您使用 null 后跟一些代码后跟 WaitForEndFrame,当协同程序恢复控制时,您仍将处于同一帧内。因为你和调用WaitForEndFrame之前还在同一帧,所以经过的模拟时间会为零,但是Time.deltaTime不会为零。所以,是的,一旦开始混合不同的 return 类型,测量时间就会变得棘手。您还应该小心在框架和固定框架之间切换。使用 WaitForFixedUpdate 将使您进入固定帧的时代。在 WaitForFixedUdpate 之后调用 Time.fixedDeltaTime 将为您提供该固定帧和前一个固定帧之间的时间,这与 Time.deltaTime 或帧的任何计时无关。