简体   繁体   English

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

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

TL,DR: is it safe to use Time.deltaTime as the wait time for the yield in a coroutine? TL,DR:在协程中使用 Time.deltaTime 作为产量的等待时间是否安全?

Often to avoid unnecessary logic inside Update() for short lived functionality I'll run a coroutine instead.通常为了避免在 Update() 内部为短期功能使用不必要的逻辑,我将运行一个协程。 For example in my game I have a slow coroutine that periodically checks the distance between NPCs and the player, if that distance is under some threshold I'll then run a more frequent coroutine with more expensive line of sight testing using raycasting etc. This seems much more efficient than checking everything constantly in Update().例如,在我的游戏中,我有一个缓慢的协程,它会定期检查 NPC 和玩家之间的距离,如果该距离低于某个阈值,我将运行更频繁的协程,并使用光线投射等进行更昂贵的视线测试。这似乎比在 Update() 中不断检查所有内容要高效得多。

My question is this: is it safe to use Time.deltaTime as the wait time for the yield, thereby simulating Update() for the duration of the coroutine?我的问题是:使用 Time.deltaTime 作为产量的等待时间,从而在协程的持续时间内模拟 Update() 是否安全? ie yield return new WaitForSeconds(Time.deltaTime); ie yield return new WaitForSeconds(Time.deltaTime);

Since deltaTime is not constant what happens if the next frame takes longer than the last - is the coroutine delayed until the next frame, or is something horrible happening like the whole frame being delayed until the coroutine finishes?由于 deltaTime 不是恒定的,如果下一帧花费的时间比上一帧长,会发生什么情况 - 协程是否延迟到下一帧,或者整个帧被延迟到协程完成后会发生什么可怕的事情? I'm tempted to allow a buffer for safety eg yield return new WaitForSeconds(Time.deltaTime * 1.2f);为了安全起见,我很想允许一个缓冲区,例如yield return new WaitForSeconds(Time.deltaTime * 1.2f); but ideally I'd like it to execute precisely every frame.但理想情况下,我希望它精确地执行每一帧。

is it safe to use Time.deltaTime as the wait time for the yield in a coroutine?使用 Time.deltaTime 作为协程中产量的等待时间是否安全?

No .没有 That's not how to use the WaitForSeconds function.这不是如何使用WaitForSeconds函数。 WaitForSeconds takes in seconds as a parameter not the tiny values provided by Time.deltaTime in every frame. WaitForSeconds以秒为参数,而不是Time.deltaTime在每一帧中提供的微小值。

Below is an example of how to use the WaitForSeconds function.下面是如何使用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");
}

As for waiting with Time.deltaTime , you usually use it in a while loop in addition to another float variable you will increment or decrement until you reach the wanted value.The advantage of using Time.deltaTime is that you can see how much waiting time is left while waiting.至于等待Time.deltaTime ,除了另一个float变量之外,您通常在while循环中使用它,您将incrementdecrement直到达到所需的值。 使用Time.deltaTime优点是您可以看到等待时间在等待时离开。 You can use that for a countdown or up timer.您可以将其用于倒计时或计时。 You also put yield return null;你也把yield return null; in the while loop so that Unity will allow other scripts to run too and your App won't freeze.while循环中,以便 Unity 也允许其他脚本运行,并且您的应用程序不会冻结。 Below is an example of how to use Time.deltaTime to wait for 3 seconds.下面是如何使用Time.deltaTime等待 3 秒的示例。 You can easily turn it into a countdown timer.您可以轻松地将其变成倒数计时器。

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");
}

If you want to check every frame there areWaitForEndOfFrame如果你想检查每一帧有WaitForEndOfFrame

There is no point to WaitForSeconds if you don't need specific time to wait for如果您不需要特定的等待时间,则 WaitForSeconds 没有意义

You can also yield return www to wait for it finish你也可以yield return www等待它完成

Update, there are CustomYieldInstruction and some of it inheritance for used in coroutine, like WaitUntil更新,有CustomYieldInstruction和一些在协程中使用的继承,比如 WaitUntil

I know that this is a bit old, but I just came across it today while looking for something that's related.我知道这有点旧,但我今天在寻找相关的东西时偶然发现了它。

Anyways, Programmer's answer is a good start.无论如何,程序员的回答是一个好的开始。 Using Time.detlaTime is not a good way to release control of a coroutine.使用 Time.detlaTime 不是释放协程控制的好方法。 For one, using a null value will get you to the next frame in simulation.首先,使用空值将使您进入模拟中的下一帧。 Second, what happens if the frame you just finished was a bit slow (or the next frame is a bit fast).其次,如果您刚刚完成的帧有点慢(或下一帧有点快)会发生什么。 Please keep in mind that the simulation (or game) runs in frames, much like the frames in a film.请记住,模拟(或游戏)以帧为单位运行,就像电影中的帧一样。 Because of this, using WaitForSeconds can have some interesting effects.因此,使用 WaitForSeconds 可以产生一些有趣的效果。 For instance, if the time you requested happens between frames, what do you think will happen?例如,如果您请求的时间发生在帧之间,您认为会发生什么? The coroutine will regain control after the requested time.协程将在请求的时间重新获得控制权。 So, if you were hoping to just shoot off a WaitForSeconds(Time.deltaTime) on each loop in the coroutine, chances are, you are skipping the occasional frame (sometimes more).因此,如果您希望在协程中的每个循环中只触发 WaitForSeconds(Time.deltaTime),那么您很可能会跳过偶尔的帧(有时更多)。

I had a coworker that did a bunch of WaitForSeconds, inside a long running coroutine and the total time that passed was anywhere between 5 to 10 seconds longer than what was expected.我有一个同事在一个长时间运行的协程中做了一堆 WaitForSeconds,所经过的总时间比预期的要长 5 到 10 秒。 Those off by part of a frame errors in the requested time will add up, and unlike nature, where errors tend to average out, these errors will always add up .通过在要求的时间框架错误的一部分那些关加起来,不像性质,其中的错误往往会平均出来,这些错误将永远积少成多 That's because the amount of time that passes will always be greater-than or equal-to the amount of time that's requested.这是因为经过的时间量总是大于或等于请求的时间量。

Programmer's answer showed you how to use Time.deltaTime to get the passage of simulation time. Programmer's answer向您展示了如何使用 Time.deltaTime 来获取模拟时间的流逝。 I should warn you that once you start using things other than null to release control of the coroutine, that Time.deltaTime might stop working for you.我应该警告你,一旦你开始使用 null 以外的东西来释放对协程的控制,那么 Time.deltaTime 可能会停止为你工作。

If you use a null follow by some code followed by a WaitForEndFrame, you will still be within the same frame when the coroutine resumes control.如果您使用空后跟一些代码后跟一个 WaitForEndFrame,则当协程恢复控制时,您仍将处于同一帧内。 Because you are still in the same frame as you were before calling WaitForEndFrame, the simulation time that has passed will be zero, but Time.deltaTime will not be zero.因为您仍然在调用 WaitForEndFrame 之前的同一帧中,所以经过的模拟时间将为零,但 Time.deltaTime 不会为零。 So, yeah, measuring time can get tricky once you start mixing different return types.所以,是的,一旦你开始混合不同的返回类型,测量时间就会变得棘手。 You should also be careful of switching between frames and fixed-frames.您还应该小心在帧和固定帧之间切换。 Using a WaitForFixedUpdate will put you into the times of the fixed-frames.使用 WaitForFixedUpdate 将使您进入固定帧的时间。 Calling Time.fixedDeltaTime after a WaitForFixedUdpate will give you the time between that fixed-frame and the previous fixed-frame, which has nothing to do with Time.deltaTime or any of timings for the frames.在 WaitForFixedUdpate 之后调用 Time.fixedDeltaTime 将为您提供该固定帧和前一个固定帧之间的时间,这与 Time.deltaTime 或帧的任何计时无关。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM