0
\$\begingroup\$

I was looking an official example for coroutines in Unity here.

However, when I call WaitAndPrint the time taken is never exactly 5 seconds.

IEnumerator WaitAndPrint()
{
    float timeStart = Time.time;
    yield return new WaitForSeconds(5);
    Debug.Log(string.Format("Time taken = {0}", Time.time - timeStart));
}

if (Input.GetKeyDown(KeyCode.R))
    StartCoroutine(WaitAndPrint());

Instead, it varies around 5.003133.

This is most likely down to the frame rate, which makes me wonder how can I make sure that a coroutine takes the precise amount of time it should take despite the fluctuating frame rate?

\$\endgroup\$
  • \$\begingroup\$ I'm wondering what Veselin asked: why does this matter? \$\endgroup\$ – jhocking Jul 21 '14 at 16:06
  • \$\begingroup\$ Precise timing of musical events at high tempi? \$\endgroup\$ – user1423893 Jul 23 '14 at 12:37
  • \$\begingroup\$ That's a pretty obscure use-case. Unity isn't designed for that kind of thing out of the box; you probably need to write a plugin using native code. \$\endgroup\$ – jhocking Jul 23 '14 at 18:04
4
\$\begingroup\$

This is most likely down to the frame rate, which makes me wonder how can I make sure that a coroutine takes the precise amount of time it should take despite the fluctuating frame rate?

I don't think you can, honestly. Coroutines are at the mercy of Update() in the same way the rest of your code is. You can't make it end between two update loops, because that's the time Unity is spending doing other stuff instead

I am kind of wondering why you need that sort of precision to begin with, though. Does it really matter if the coroutine ends when the frame starts, or 3ms before that?

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ This sort of precision would be required when generating musical events at regular intervals at higher tempi. Subdividing of pulse and the like. \$\endgroup\$ – user1423893 Jul 23 '14 at 12:42
2
\$\begingroup\$

Coroutines aren't threads or processes or anything special like that. They're just callbacks given to the engine to call when a specific condition is met. If you yield null, the coroutine will be called every frame.

Every frame, the engine calls all coroutines that are ready at that time, all together in a block (either right before or right after calling all the .Update()'s, not sure which). It will only call a WaitForSeconds routine AFTER that number of seconds has elapsed, so it will come up during the frame after that time has passed.

You can only really do things in unity in increments of frames (or physics updates), anyway. You surely can't draw something to the screen at a specific exact time, you have to wait for the next frame to happen.

Here's an in-depth article on how coroutines work, and a couple threads that I've bumped into in unity-land relating to them, which link off into other resources as well:

http://www.altdev.co/2011/07/07/unity3d-coroutines-in-detail/

http://answers.unity3d.com/questions/751178/when-using-coroutines-what-should-i-be-wary-of.html

| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

Actually it is normal if the dvalue is under 0.01. And that 0.01ms won't bother your game. I've tested. That 5 second will be different each time you launch the game.

| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

You can never make sure a coroutine takes a precise amount of time. As you said, it's the frame rate. You can get super close, but it'll never be spot on.

The time between frames will always differ, based on hardware. Thus you will almost always overshoot your specified time. Imagine you are at 4.89 seconds and the next frame takes 0.16 seconds to update. You'd be at 5.05 seconds on the new update. You're unable to control that.

What you can control is how you use that information given. If you had some code that needed to execute at the end of the 5 seconds. Do what you did before, get the difference in time and advance to whatever the execution would be at that time.

In your example that you would execute some code as though .003133 seconds had already passed. Now this isn't applicable in all situations - such as you wanting to just wait for an exact period of time.

| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.