0
\$\begingroup\$

I'm new to Unity and I was learning the usage of coroutines. Is calling a coroutine as good as a delay() function? Does Unity have a delay() function?

\$\endgroup\$

closed as unclear what you're asking by Philipp, Almo, MichaelHouse Aug 18 at 18:50

Please clarify your specific problem or add additional details to highlight exactly what you need. As it's currently written, it’s hard to tell exactly what you're asking. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.

  • 3
    \$\begingroup\$ I've used Coroutines in the past and had no issue performance-wise. Is there something that you are worried about using them? \$\endgroup\$ – TomTsagk Aug 6 at 11:41
  • 5
    \$\begingroup\$ Can you show us an apples-to-apples comparison of the two ways you're thinking of implementing your feature? Right now it's unclear what you have in mind with delay(). There are lots of ways to create a delay, and other than locking the main thread, they'll tend to all work similarly enough, so we need details to understand the specific differences for your case. \$\endgroup\$ – DMGregory Aug 6 at 11:53
1
\$\begingroup\$

ratchet freak's answer is an excellent explanation of the differences between using Thread.Delay() and coroutines in Unity. To address your second question, I suspect what you're looking for is WaitForSeconds.

From the documentation:

public class WaitForSecondsExample : MonoBehaviour
{
    void Start()
    {
        StartCoroutine(Example());
    }

    IEnumerator Example()
    {
        print(Time.time);
        yield return new WaitForSeconds(5);
        print(Time.time);
    }
}

However, be aware that this example just starts the coroutine, it doesn't wait for it. For example, say you had some code in the Start function after the call to StartCoroutine. That code would get executed immediately, not after 5 seconds as you might expect. If you wanted to wait until after the the coroutine finished, you would have to either call that code from the coroutine, or set a value that gets checked somewhere else (like in Update), or wait for it inside another coroutine, etc.

For a simple timer, that can get messier than it needs to be. To circumvent that clutter, I like to use this free async/await library, which allows you to write code like the following

async void Start()
{
    print(Time.time);
    await new WaitForSeconds(5);
    print(Time.time);
}

Which does logically wait for the WaitForSeconds to finish before executing the code after it, without suspending the entire thread. In my opinion this is a much cleaner alternative to Delay(). Of course, async/await has its own gotchas and can be a little confusing if you've never dealt with it before. You can read more about using it with Unity here.

\$\endgroup\$
  • \$\begingroup\$ You can write code equivalent to the second example without an extra library like so: IEnumerator Start() { ...yield return new WaitForSeconds(5);...} \$\endgroup\$ – DMGregory Aug 6 at 19:27
  • \$\begingroup\$ Did not know that, thanks! \$\endgroup\$ – pmain8 Aug 6 at 19:30
0
\$\begingroup\$

The problem with delay() as traditionally implemented (stopping the thread until it can continue again) means exactly that, it stops the thread and it cannot do anything else.

One underappreciated feature of unity (and in fact most game engines and gui frameworks) is that most of the main logic is executed on a single thread. This makes programming a lot easier as by default you don't have to deal with hairy multithreading.

However this means that if you don't allow that thread to continue working on other tasks (including stuff like taking input, updating the screen etc.) the entire program just stops responding.


But you still need some way to pause a set of actions action and resume it later.

This can be done explicitly by splitting the sequence of actions up in multiple sections and scheduling those to run at the correct times using timers or the update function that gets called every frame (which then dispatches to the correct section when it's ready for the next step) or implicitly by using the built-in coroutine system.

The coroutine system takes the yielded value and uses that to decide when to resume it. One possibility is a fixed delay or a conditional wait.

So the core system has a list of running coroutines along with their last yielded value. It then loops over those yielded values and tests whether to resume it. I like to believe that that one my previous post inspired this system.

\$\endgroup\$
  • \$\begingroup\$ Hmm... your previous post is from 2013, but Unity already had Coroutines in 2012, did it not? \$\endgroup\$ – DMGregory Aug 6 at 13:13
  • \$\begingroup\$ @DMGregory Maybe, I wasn't that involved in that ecosystem back then. And I certainly cannot prove that my post actually inspired anything. AFAIK it did coincide with its rise in popularity. \$\endgroup\$ – ratchet freak Aug 6 at 13:27

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