Coroutines in Unity

Coroutines in Unity (how and when to use them)

In Scripting Basics by John FrenchUpdated 95 Comments

If you’re new to Unity, it’s possible that you’ve written a lot of your code inside the Update function.

This may mean that you’re checking boolean conditions to manage states and using if conditions to call functions and to deploy different blocks of code at different times.

Which is fine, especially when you’re just getting started with scripting in Unity.

However…

If you’ve ever tried to delay a function or have it wait for another action to finish, or if you’ve tried to pause it halfway through or you want to queue up a series of actions to take place one after another, you may have found this difficult to do inside Update or using a regular function.

But don’t worry, because that’s where Coroutines come in.

Coroutines explained (video)

For an overview of how to use coroutines in Unity try my video, or continue to the full article below.

What are Coroutines in Unity?

Code that’s called inside of Update usually takes place all at once during the current frame.

Coroutines, on the other hand, allow you to execute game logic over a number of frames.

Put simply, this allows you to pause a function and tell it to wait for a condition or action to occur before continuing. This allows you to split up its functionality into a number of steps that can be executed in order.

This is fantastic for carrying out actions that would otherwise be impossible, inefficient or just plain difficult to do inside of Update alone.

And while it is possible to achieve many of the functions that Coroutines are designed for using other techniques, Coroutines can be extremely convenient, easy to use and very efficient.

So long as you use them the right way.

So, in this post, you’ll learn how to write a Coroutine, how to start it, stop it and pause it, as well as some best practices for when you should, and shouldn’t, be using them. So that you can be confident that you’re using Coroutines the right way in your project.

What you’ll find on this page:

Why use a Coroutine?

Coroutines are ideal for setting up game logic that needs to takes place over time (multiple frames instead of one).

This may not sound like much at first, but this can be incredibly helpful.

To get an idea of just how useful Coroutines can be, consider the following example.

Let’s say I have a tank, and when I click on the map I want that tank to turn to face where I clicked, move towards the position and, when it gets there, wait 1 second before firing.

Like this….

Coroutine example in Unity

Giving this tank a series of instructions should be easy, or so it seems.

Basically I’m giving the tank a To-Do list…

  • Turn to a specific angle.
  • Move to a specific point.
  • Wait for 1 second, then fire.

Easy right?

While the logic to achieve this seems simple, if I wanted to do this in Update, it can quickly become confusing and difficult to manage.

To prevent all of the To-Do list items from happening at the same time (which is how Update normally works) I have to keep checking to see if the tank is supposed to be turning, moving or firing at any given moment.

In scripting, using Update based functions, it would look something like this:

// Please don't do this

bool tankMoving;
bool facingRightWay; 
bool tankInPosition;
float timer;

void Update()
{
     if(Input.GetMouseButtonDown(0))
        {
            tankMoving = true;
        }

     if (tankMoving)
        {
            MoveTank();
        }
}

void MoveTank()
    {

        if (facingRightWay == false)
        {
            if (angleIsWrong)
            {
                TurnTank();
            }
            else if (angleIsCorrect)
            {
                facingRightWay = true;
            }
        }

        if (facingRightWay && tankInPosition == false)
        {
            if (positionIsWrong)
            {
                MoveToPosition();
            }
            else if (positionIsCorrect)
            {
                tankInPosition = true;
            }
        }

        if (facingRightWay && tankInPosition && timer < 1) 
        {
            timer += Time.deltaTime;
        }
        else if (facingRightWay && tankInPosition && timer > 1)
        {
           FireTank();

           facingRightWay = false;
           tankInPosition = false;
           tankMoving = false;
           timer = 0;
        }
    }

As you can see, it’s a lot more complicated than it needs to be.

But that’s not even the biggest issue with this method…

While researching for this article, I did manage to get this to work using only Update based code, however, it wasn’t easy at all.

For example, my first attempt had the tank infinitely spinning, firing bullets immediately in random directions whenever I clicked.

Not what I wanted.

This happened because my fire function wasn’t checking to see if the other steps had already taken place. I found it difficult to keep track of which conditions needed to be true, I made a mistake and so everything was taking place out of turn.

Which is the real problem when trying to execute this kind of ‘staged’ logic in an Update loop.

Apart from being inefficient, it’s counter-intuitive and difficult to manage.

But it doesn’t need to be.

Using a Coroutine makes it much easier.

Here’s the same logic again, this time inside a Coroutine:

void Update()
{
    if(Input.GetMouseButtonDown(0))
    {
        StartCoroutine(MoveTank());
    }
}

IEnumerator MoveTank()
    {
        while(facingWrongWay)
        {
            TurnTank();
            yield return null;
        }

        while (notInPosition)
        {
            MoveToPosition();
            yield return null;
        }

        yield return new WaitForSeconds(1);
        Fire();    
    }

This time, the code works more like a To-Do list with each action being executed after the last has completed.

Unity processes each of the While Loops until their condition is no longer true, before moving on to the next.

This isn’t actually any different from how Unity executes a regular function except that, now, the logic is being carried out over multiple frames instead of one frame.

This works because of the yield keyword, which tells Unity to stop what it’s doing and continue again on the next frame.

The end result is a sequence of events that’s easier to write and easier to manage.

It’s also more efficient, as Unity no longer has to check for conditions that aren’t relevant yet.

And, once all of the actions are completed, the Coroutine ends.

When to use a Coroutine in Unity

Coroutine Actions Visualised

It’s worth considering using a Coroutine whenever you want to create an action that needs to pause, perform a series of steps in sequence or if you want to run a task that you know will take longer than a single frame.

Some examples include:

  • Moving an object to a position.
  • Giving an object a list of tasks to carry out (like in the To-Do list example earlier).
  • Fading visuals or audio in and out.
  • Waiting for resources to load.

These are the kind of tasks that Coroutines are well suited for.

But how do you actually write one?

How to write a coroutine

A Coroutine is laid out in a similar way to a regular function, with a couple of key differences.

First, the return type of a Coroutine needs to be IEnumerator, like this:

IEnumerator MyCoroutine()
{
    // Code goes here!
}

If you’re not familiar with IEnumerator, don’t worry.

All you really need to know about it right now is that this is how Unity splits the function’s execution across multiple frames.

Just like normal functions, you can pass parameters into a Coroutine.

IEnumerator MyCoroutine(int number)
{
    number++;
    // Code goes here.
}

Variables that you initialise inside the Coroutine will hold their value for its duration.

Also, unlike regular functions, Coroutines allow you to pause the code while it’s executing using a yield statement.

How to pause a Coroutine in Unity (Yield)

Pause a function in Unity visualised

There are a few different types of yield statement that will pause a Coroutine and which one you use depends on how long you want to pause the method for.

In all cases, however, you’ll need to start with the keywords yield return at the point you want the function to be interrupted.

Why these keywords?

Yield indicates that the method is an iterator and that it’s going to execute over more than one frame, while return, like in a regular function, terminates execution at that point and passes control back to the calling method.

The difference is that, with a Coroutine, Unity knows to continue the method where it left off.

What follows yield return will specify how long Unity will wait before continuing.

So, what are the options?

Yield Return Null (wait until the next frame)

Yield return null instructs Unity to wait until the next frame before continuing.

Combining yield return null with a while Loop creates mini Update Loops. Like this.

IEnumerator MyCoroutine()
    {
        int i = 0;

        while (i < 10)
        {
            // Count to Ten
            i++;
            yield return null;
        }

        while (i > 0)
        {
            // Count back to Zero
            i--;
            yield return null;
        }

        // All done!
    }

Unity will work through the first loop, counting one number every frame and then the second, counting back down by one each frame, until the end of the code block.

Without yield return null, all of the code would be executed at once, just like a regular function.

Wait For Seconds (wait for a period of time)

Wait For Seconds or Wait For Seconds Real Time (which uses unscaled time) allows you to specify an exact amount of time to wait. It can only be used inside a Coroutine (i.e. it doesn’t work in Update).

Just like before, you’ll need to use Wait for Seconds with the yield return statement and, in this case, usually the new keyword for it to work.

In scripting it looks like this:

IEnumerator WaitFiveSeconds()
    {
        print("Start waiting");

        yield return new WaitForSeconds(5);

        print("5 seconds has passed");
    }

Using Wait for Seconds like this works best for one-off waits.

For a repeating delay, it’s slightly better performance to cache the Wait for Seconds object first.

This also means you won’t need the new keyword. Like this:

WaitForSeconds delay = new WaitForSeconds(1);

    Coroutine coroutine;

    void Start()
    {
        StartCoroutine("MyCoroutine");
    }

    IEnumerator MyCoroutine()
    {
        int i= 100;

        while (i>0)
        {
            // Do something 100 times
            i--;

            yield return delay;
        }
        // All Done!
    }

Wait for Seconds Real Time performs the exact same function, but uses unscaled time instead. Which means it will still work even if you alter the time scale, like when pausing the game.

Like this:

IEnumerator WaitFiveSeconds()
    {
        // Pause the game
        Time.timeScale = 0;

        yield return new WaitForSecondsRealtime(5);

        print("You can't stop me");
    }

Yield Return Wait Until / Wait While (wait for a delegate)

Wait Until pauses execution until a delegate evaluates to true, whereas Wait While waits for it to be false before proceeding.

Here’s how it looks in scripting:

int fuel=500;

    void Start()
    {
        StartCoroutine(CheckFuel());
    }

    private void Update()
    {
        fuel--;
    }

    IEnumerator CheckFuel()
    {
        yield return new WaitUntil(IsEmpty);
        print("tank is empty");
    }

    bool IsEmpty()
    {
        if (fuel > 0)
        {
            return false;
        }
        else 
        {
            return true;
        }
    }

This is an easy to read version of Wait Until being used, with an external function being used to evaluate the condition.

However, you might not write it out like this.

As it’s possible to achieve the same result with a Yield Return Null statement inside of a While Loop, (like in the example earlier) you might not think to use Wait Until or Wait While at all.

That is unless you had a specific reason to do so, for example, to add extra logic to the true and false conditions in a function that sits outside of the Coroutine.

A benefit, however, of using Wait Until or Wait While instead of a While Loop is convenience. When using the lambda expression, it’s possible to check variable conditions, just like you would in a While Loop, on a single line of code.

Like this:

IEnumerator CheckFuel()
    {
        yield return new WaitWhile(() => fuel > 0);
        print("tank is empty");
    }

More information about Wait Until and Wait While can be found in the Unity documentation.

Wait For End of Frame

This specific instruction waits until Unity has rendered every Camera and UI element, just before actually displaying the frame. A typical use for this would be taking a screenshot.

IEnumerator TakeScreeshot()
    {
        // Waits until the frame is ready
        yield return new WaitForEndOfFrame();

        CaptureScreen();
    }

If you’re interested you can find an example of how to actually capture the screenshot here.

Wait for another Coroutine

Finally, it’s possible to yield until another Coroutine, that’s triggered by the yield statement, has finished executing.

Simply follow yield return with a Start Coroutine method, like this:

void Start()
    {
        StartCoroutine(MyCoroutine());
    }

    IEnumerator MyCoroutine()
    {
        print("Coroutine has started");
        yield return StartCoroutine(MyOtherCoroutine());
        print("Coroutine has ended");
    }

    IEnumerator MyOtherCoroutine()
    {

        int i = 3;

        while (i>0)
        {
            // Do something 3 times
            i--;
            yield return new WaitForSeconds(1);
        }
        print("All Done!");
    }

The code will continue after the Coroutine you start completes.

Speaking of starting Coroutines…

How to start a Coroutine

There are two methods of starting a Coroutine.

You can start a Coroutine using its string, like this:

void Start()
    {
        StartCoroutine("MyCoroutine");
    }

    IEnumerator MyCoroutine()
    {
        // Coroutine business...
    }

Or you can start a Coroutine by referencing the method name (like you would with a regular function).

Like this:

void Start()
    {
        StartCoroutine(MyCoroutine());
    }

    IEnumerator MyCoroutine()
    {
        // Do things...
    }

Both techniques are overload methods of Start Coroutine.

Mostly they’re very similar, but with a couple of key differences.

Firstly, there’s a slight performance hit for using the string method over the name method.

Also, when starting a Coroutine using a string, you can only pass in one parameter, like this:

void Start()
    {
        StartCoroutine("MyCoroutine", 1);
    }

    IEnumerator MyCoroutine(int value)
    {
        // Code goes here...
    }

However,

You’ll notice the biggest difference between using one method over another when you come to actually stop it.

How to end a coroutine

Coroutines end automatically once their code has been executed. You don’t need to explicitly end a Coroutine.

However,

You may wish to end a Coroutine manually before it has finished. This can be done in a few different ways.

From inside the Coroutine (with Yield Break)

End a coroutine in unity (visualised)

Simply adding the yield break statement will end a Coroutine before it’s finished.

This can be useful for exiting a Coroutine as a result of a conditional statement, for example.

Like this:

IEnumerator MyCoroutine(float value)
    {
        if (value > 10)
        {
            // Do one thing
            yield break;
        }

        // Do another
    }

This allows you to create conditional code paths that can exit out of Coroutines.

But what if you want to stop a Coroutine unexpectedly. For example, you want to cancel what the Coroutine was doing entirely.

Luckily, Coroutines can also be stopped externally.

End from outside of a Coroutine (with Stop Coroutine)

How you end a Coroutine depends partly on how you started it.

Stop a Coroutine using its String

If you started a Coroutine using its string, you can use that same string to stop it again.

Like this:

StopCoroutine("MyCoroutine");

If, however, you’ve started multiple Coroutines using the same string, all of them will be stopped when using this method.

So what if you want to stop one specific instance of a Coroutine?

How do you do that?

Stop a Coroutine by reference

It’s possible to stop a specific Coroutine instance if you store a reference to that Coroutine when you start it.

Like this:

bool stopCoroutine;
Coroutine runningCoroutine;

    void Start()
    {
        runningCoroutine = StartCoroutine(MyCoroutine());
    }

    void Update()
    {
        if (stopCoroutine == true)
        {
            StopCoroutine(runningCoroutine);
            stopCoroutine = false;
        }
    }

    IEnumerator MyCoroutine()
    {
        // Coroutine stuff...
    }

Whichever method you use, it’s generally good practice not to mix and match.

For example, if you start a Coroutine with a string, that’s how you’ll need to end it.

If, however, you’re in any doubt, there is one easy method that is guaranteed to stop a Coroutine.

Stop All Coroutines on a MonoBehaviour

The easiest and most surefire method for stopping a Coroutine is by calling Stop All Coroutines.

Like this:

StopAllCoroutines();

This stops all Coroutines started by the script on which it is called so it won’t affect other Coroutines running elsewhere.

It does, however, stop Coroutines that were started by the behaviour on which it was called, even if they’re in other scripts on other objects.

For example…

If Script A runs a Coroutine that starts a Coroutine on Script B, calling Stop All Coroutines from Script A will stop both of them.

However, using the same example, if you call Stop All Coroutines from Script B. Even if you call it from inside the Coroutine on that script, it won’t stop anything, because Script A started it.

So remember to call Stop All Coroutines from the behaviour that started them.

Otherwise, it won’t work.

Does destroying the Game Object stop the Coroutine?

Yes, it does.

Destroying or disabling a Game Object will end any Coroutines that were called from it, even if they’re in other scripts on other Game Objects.

However,

This only works at the Game Object level. Disabling the script is not enough to stop the Coroutine.

And if a Coroutine on one object was called by a different script, even destroying that object will not end the Coroutine, as Coroutines are tied to the Game Object that called them.

What does “Not all code paths return a value” mean?

If you’re seeing this error when writing a Coroutine (probably as soon as you start writing it) don’t worry.

This only appears because, as Coroutines have a return type (IEnumerator) there needs to be something to return. In this case, you need a yield return or yield break statement somewhere in the code block and, chances are, you just haven’t written it yet.

It’s usually best to just ignore the error but, if you want to avoid seeing it while you’re writing the Coroutine, then you can add yield break to the bottom of the function.

However…

Unless you’re stopping it early, you shouldn’t need to end a Coroutine with Yield Break, as Coroutines end themselves once they complete.

So, if you’ve finished writing your Coroutine, and you’re still seeing this error then it’s probably because your function doesn’t include any yield statements at all.

Which may mean that you’re not actually splitting your logic across multiple frames (i.e. your Coroutine isn’t waiting for anything to happen).

If this is the case then, chances are, you don’t actually need to use a Coroutine at all and it’s probably better to use a regular function instead.

Coroutine Best Practices

Coroutines can be extremely helpful.

But… they’re not always the best option.

It’s important to remember what’s good (and what’s not so good) about Coroutines so that you can get the most out of them, know when to use them and know when to try something else instead.

For example…

Avoid overlapping logic when using Coroutines

It’s possible to trigger multiple Coroutines that overlap, with each trying to execute the same logic and change the same values all at once.

Not great…

While you can’t explicitly check if a Coroutine is already running you can usually avoid this by simply stopping any Coroutines on a script before triggering a new one.

This may or may not be an option for you (depending on how many Coroutines you’re planning to run at once) but, for the most part, it’s an easy safety net.

Set and forget

Coroutines work best when you can ‘set and forget’ them, so it may help to avoid any logic that needs to change while the Coroutine is executing.

Remember the To-Do list example earlier in this post?

The tank knows what to do, and in what order to do it in.

Plus, with the use of some conditional logic, it could even know what to do when presented with a number of different situations.

However,

Trying to make changes or give the tank new instructions while it’s working through its list could become problematic. We’d have to start checking the state of the tank with booleans to know what it was up to.

Which is exactly what we were trying to avoid by using a Coroutine in the first place.

Coroutines vs Invoke vs Async

Coroutines can be great, but sometimes there may be other options that are more suitable.

For example, if you just want to delay the start of a function, Invoke will do that for you, while Invoke Repeating is an easy choice for repeating the same function over and over.

It’s also possible to use Async and Await functions in Unity, which work in a similar way to Coroutines.

One of the biggest differences between Async and Await functions and Coroutines is that they can return a value while, generally, Coroutines can’t do that.

So which is the best option to use?

Like with many tasks, there is often a method that is technically the best.

However, this is often true of most things.

Sometimes the best method for you to use is the option that’s most appropriate but that’s also within your ability to execute confidently.

And if that’s Coroutines, and they’re a good fit for what you’re trying to do, then you should use them.

Now I want to hear from you

I want to know if you’ve been using Coroutines in your project?

Have they helped you, or have they actually caused you more trouble than they’re worth?

Or maybe you’ve got a tip for using Coroutines that other people need to know.

Whatever it is, let me know by leaving a comment below.

Image Attribution

Icons made by Google from www.flaticon.com
Icons made by Tomas Knop from www.flaticon.com
John French profile picture

by John French

Game audio professional and a keen amateur developer.

Get Game Development Tips, Straight to Your inbox

Get helpful tips & tricks and master game development basics the easy way, with deep-dive tutorials and guides.

How this content was created

This article was written using first-hand research and experience, without the use of AI. For more information on how Game Dev Beginner articles are written, see my writing policy.

Comments

  1. This is handsdown one of the best explanation on coroutines.
    Thank you for your time and effort

  2. I never ever commented on a blog post but this post was the best I ever read thanks dude

  3. Incredibly helpful, and thorough, explanation of coroutines! Thanks for the effort and time to explain this, John!

  4. Very nice guide about Coroutines! Recently I used coroutine for the spawner of my game where it spawns every time the enemies get killed or cleared. Coroutines are awesome!

  5. Maybe it’s worth noting here in the comments that they are significantly slower than Update methods in big numbers like 5k+

    1. Author

      Thanks for the tip. I agree, it’s worth noting that there’s a performance overhead for using a Coroutine in place of Update, however it’s entirely dependant on how you Use the Coroutine. For example, if you’re doing something every frame Update is probably going to be cheaper, but it might still be more convenient to use a Coroutine. However… If you’re doing something every 1 sec, a Coroutine or Invoke Repeating can be much, much more efficient, despite the initial overhead. I haven’t tested this personally, there’s a helpful test that someone published in this post. Thanks again for your feedback. I appreciate it.

  6. Idk what is going on. EVERYBODY use them like that, but I allways have an error like I need to write `string` in `StartCoroutine()`. And when I do so it do nothing!(

    1. Author

      Any chance you’re missing the parentheses after passing in the Coroutine? They’re easy to miss.

      1. You’re John the GREATEST! That was SO easy and I was so DUMB! Thank you a lot!

        1. Actually it’s not needed in that case. If you look earlier in the code, they defined a private IEnumerator named coroutine. Then in the Start function they assigned it to the function WaitAndPrint. Then they called StartCoroutine on it. So because it was already defined there was no need for the parenthesis.

  7. Amazing article, very easy to understand with clear examples. Thank you for that, we need more of this kind of explanations!

  8. I’ve read dozens of articles on c# and unity the last couple of weeks. Almost none of which reach your level of tutoring. Tidy and explanatory.
    Thank you for sharing and please keep’em coming!

  9. Very clear and well explained! Please keep writing tutorials like this!

  10. Awesome tutorial! Hope to see more of that!

    By the way, I think there’s an error on the first example using coroutines. You say something like that:

    while (notInPosition)
    {
    MoveTank();
    yield return null;
    }

    Inside the MoveTank method, so, it looks like a recursive call.

    1. Author

      Good spot, thank you. I’ve changed the name of the moving function example.

  11. Great article! I like how you try to explain as much as you can and also put references for further information.

    Just out of curiosity, when both Coroutine and Invoke can be used is there some situation where Coroutine would be more suitable? Or can we always use Invoke for the sake of simplicity?

    1. Author

      Thanks! To answer your question, feature-wise Invoke delays a function by an amount of time, while coroutines split logic out over multiple frames. For example a coroutine can stop and start while Invoke just delays the call. So their features are different. Off-hand I don’t know if there’s a performance benefit to using Invoke over, for example, a Coroutine that only adds a delay, however I’d suggest it’s easier than using a coroutine if that’s all you want to do. Unity docs seem to recommend coroutines over Invoke, but I haven’t compared the two closely.

  12. Amazing article as usual. You are the best tutor available for beginners. Thanks.

  13. Kudos John, great article on Coroutines. They really clicked for me after reading this.

  14. The real magic words on this were “Think about it like a to-do list”. Best Coroutine explaination ever. Bookmarked your blog in the hope to get more of this kind to get more into things like using interesting design patterns or smth. like that.

    Btw:
    I did a coroutine to achieve a textbox that is printing a string one char after another like in old rpg’s. Could be another example for this blog 😉

    1. Author

      Thanks so much! I’m really glad you liked it. Good idea on the text example.

  15. Just want to echo what others have said here, I’ve been using Unity for a while now but wanted to quickly double check something on coroutines and found this article. So well written and so thorough, learned things I never knew! I also love your other articles John, you’ve got an excellent way of explaining things in a very simple, concise way. Thank you for your service to the field!

    And I should say also – your music is awesome. I already own your music pack! 🙂

    1. Great article and easy to understand. Hope to see more like this.

      I usually use coroutine to load/instantiate assets.

  16. I have ADHD so it can be really hard for me to follow long reads but this one was fantastic. I really appreciate it!

  17. Best explanation ever. Thank you so much.
    And I want how to use Async and Await next

  18. Your writing was extremely helpful and straightforward to a total newbie like me. Great thanks!

  19. John, you did a good job, thank you for such an explanatory topic of coroutin, you are a professional in your field, good luck with your projects.

  20. Great article John French, very helpful and life saver. Tons of thanks for your effort.
    I was trying to achieve all of your examples. Probably I made a mistake about it but even though I copy pasted your one of your example, there is an error like that:

    “WaitUntil’ does not contain a constructor that takes 1 arguments.”

    I thought you’d like to know if there is anything to change in code for other readers.

    1. Author

      Thank you! WaitUntil takes a delegate, so in my example in the post, I’ve passed in a reference to a function that returns a bool. Note that I can’t just pass in a bool variable, and I can’t pass in the function name with parentheses in place of a bool.

  21. Great article John. I use the Tanks example in my class. Coroutines are something students need some extra help and will point them to this. I must admit that my own understanding of these is challenged by your one example of returning a new Coroutine. I usually just return the IEnumerable, not a StartCoroutine call. I would think both print statements would occur in the same frame. Have you tested this? It seems like a good way to get multiple coroutine executing every frame.
    void Start()
    {
    StartCoroutine(MyCoroutine());
    }

    IEnumerator MyCoroutine()
    {
    print(“Coroutine has started”);
    yield return StartCoroutine(MyOtherCoroutine());
    print(“Coroutine has ended”);
    }

    1. Author

      Thanks Roger, I appreciate it. To answer your question yep this definitely works. It was tested at the time and I double-checked it just now, just to be sure. Thanks again.

  22. This is the best Coroutine explanation I have ever read,I hope you continue your great job.

  23. What if I would like to check if something has already happened OR if enough time has passed? For example I have a buff that gives me extra bonus damage for next attack, but it lasts 10sec. If I use it up, the buff will disappear, if not, it will disappear by itself after 10 seconds. I have no clue how it could look like. I tried to make it with WaitUntil Loop, but the part with checking time doesn’t work at all.

    1. Author

      A simple way to do this would be to create a timer float inside the coroutine at the start, and then add time to it (using Delta Time in the while loop) until the 10s has elapsed. Then when the time runs out the coroutine moves past the while statement and processes whatever code is after it. You could combine the while statement with whatever value you’re using to see if it’s been used up or not.

      Something like:

      
      IEnumerator Power()
      {
          float timeElapsed=0;
          while(timeElapsed < 10 && powerNotUsedUp)
          {
              //player has the power
              timeElapsed += Time.deltaTime;
              yield return null;
          }
      }
      

      This is off the top of my head, but something like that should work.

      1. I checked, but it doesn’t work for me. I have an absorbing shield and it should disappear after 10 seconds or if the shield is broken. I’ve tried around 20 options with while, if, for and WaitUntil loops at the moment.

        Depending on the syntax, either countdown is working, but not working with condition when absorb <= 0 or vice versa, absorb <= 0 works, but no countdown.

        For example:
        IEnumerator IceArmor()
        {
        yield return new WaitUntil(isIceArmorDone);
        absorb = 0;
        iceArmor = false;

        yield return null;
        }

        bool isIceArmorDone()
        {
        float timeElapsed = 0;
        if (absorb 10)
        {
        return true;
        }
        else
        {
        timeElapsed += Time.deltaTime;
        return false;
        }
        }

        Here timeout doesn’t work at all. In IEnumerator I tried with while/if loop and there works only timeout (because it checks absorb state only on coroutine beginning, not in real time I guess).

        Sorry for bothering you with such examples from the hat, but I have no idea how to bite it anymore. I know learning is a process, but I’m a bit stuck here. Thanks for the answer because it gave me an extra boost on how to try to bite it, and it taught me a lot by the way.

        1. Author

          So, assuming I’ve understood you correctly. You want the shield to break if the absorb value drops below zero (i.e. the shield was used up) or after 10 seconds. Whichever comes first.

          This script will do that:

          
          using System.Collections;
          using System.Collections.Generic;
          using UnityEngine;
          
          public class TestScript : MonoBehaviour
          {
              public float absorb=10;
              bool iceArmor;
          
              private void Start()
              {
                  StartCoroutine(IceArmor());
              }
          
              IEnumerator IceArmor()
              {
                  iceArmor = true;
                  float timeElapsed = 0;
          
                  while (timeElapsed < 10 && absorb > 0 )
                  {
                      timeElapsed += Time.deltaTime;
                      yield return null;
                  }
          
                  absorb = 0;
                  iceArmor = false;
          
                  Debug.Log("Ice Shield Broke");
              }
          }
          

          I’ve triggered it in Start for you to try, and if you want to drop the absorb value you can do it in the inspector while the game is running.

          Hope that helps.

          1. Holy crap, it works!

            On one of my tries I had almost the same script, the difference was only I hadn’t “iceArmor=true” on beginning. I didn’t give it to coroutine, because it comes from another one (more complicated thing). I don’t know why script skipped while loop and just go forward. Maybe I just missed one small detail…

            Thank you so much John! I’m really grateful for your help, time and lessons!

  24. hye,
    Thank you for this explanation, it’s very interesting. There is one thing I don’t understand. I would like to know if the method “TurnTank()” is part of another class, would the tank class be able to handle it in its coroutine? I understand how to use corroutines when everything is done in the same class, but how do you use a method with complex actions that belongs to one class in a corroutine of another class?

    Good day,

    1. Author

      Hi, so yes that should work. So long as you have a reference to the other class you can call otherScript.TurnTank(); When you’re in the while loop, the coroutine basically works like Update.

  25. Hey dear John,Than you so much for your amazing blog and tutorials,i hope you will share new stuff soon,
    I don’t know if there is an error here on the stopCoroutine reference name or not,i hope you can check this:

    bool stopCoroutine;
    Coroutine runningCoroutine;
    void Start()
    {
    runningCoroutine = StartCoroutine(MyCoroutine());
    }
    void Update()
    {
    if (stopCoroutine == true)
    {

    /*the name of the coroutine below is wrong i guess*/

    StopCoroutine(coroutine);
    stopCoroutine = false;
    }
    }
    IEnumerator MyCoroutine()
    {
    // Coroutine stuff…
    }

    1. Author

      Thank you, and yes more articles are on the way! Thanks for catching that typo, I’ve updated the article.

  26. I’m new to game dev, and I have this 2d fighting game project and I think i’ve been using too many Coroutines in order to change animations states…
    So, my question is: are they being used well or are there better ways?

    1. Author

      It really depends. Basically, coroutines are pretty much the same as Update, except that you can stage the logic inside them to take place over multiple frames. So if for each use case you’re starting something that has a start, middle and end, a Coroutine is probably a good option. However, there are lots of ways to manage state and, for what you’re doing there may be a better option, especially if you’re finding it difficult to manage what is happening. My suggestion would be to post to the Unity forums, with some detail about what you’re trying to do and how you’re trying to do it, and see what others think. Hope that helps.

  27. For some reason, when I try to make a coroutine, it just tells me “not all code paths return a value”, and I have found no way to fix it. Can anyone find out why this is happening?

    1. Author

      This happens when there’s not a yield return or a yield break in the function. So, usually, when you first write the coroutine, before you add a yield statement, you’ll see this error. You can temporarily fix it by just adding yield break at the bottom of the coroutine, and take it out when you’re finished writing it.

  28. I think this has to be your best written article yet.

    I’m literally in awe with how easy you made it to understand Coroutines.

  29. Thanks so much for this, it really helped me understand better. Still, I’ve been battling for days to get one coroutine to work – even when the wait until condition was met, the rest of the coroutine just wasn’t executing. The condition was a boolean that was passed as a parameter to the coroutine:
    WaitForFlag(bool flag))
    {…
    yield return new WaitUntil(() => flag);

    do some more stuff }.

    Also, the flag passed in was from another class:
    StartCoroutine(WaitForFlag(OtherClass.myFlag)

    Eventually, I tried hard-coding the condition into the coroutine, instead of passing in as a parameter:

    StartCoroutine(WaitForFlag());

    WaitForFlag()
    { …
    yield return new WaitUntil(() => OtherClass.myFlag);

    do some more stuff }

    This worked! but I’ve no idea why – any suggestions please?

    1. Author

      So I think what’s happening here is that the coroutine cannot check the original boolean, only the value you passed in. A boolean is a value type, not a reference type, meaning that if you pass a boolean into a function as a parameter you’re simply copying the value at the time, it’s always going to be the static value that you pass in when you call it. Even if the original boolean changes, you already passed in true or false, so the condition is never met. Instead, if you make a function that returns true or false, and reference the original variable directly, then that should work, since the change can actually be detected at the source.

      1. Thanks for your reply John, I think I understand it 🙂 Clearly I need to study value types and reference types. For this example, I think it’s OK to leave as it is, but I was trying to accomodate a future possibility of needing to WaitUntil a different parameter, by having a single Coroutine to cover different requirements. Sometimes I guess it’s better not to try to be too clever :))

  30. I swear you write some of the best posts! I’ve learned a lot from several of your blog posts at this point (InputSystem and rotation were some of the others.) Just the right amount of explanation without overexplaining.

  31. Thanks so much for this. I am an amatuer too and this was a good in depth knowledge on coroutine, thanks so much for this.

  32. John, your website is awesome! It has been a great source of information as I rebuild my iOS mobile game in the Unity system! Thanks so much for sharing your wisdom 🙂

  33. This is amazing. I’m fairly new to this game programmer/developer gig, learning with Unity tutorials and courses- but many intermediate notions are a bit harder to grasp. Your articles have been a great help in understanding those concepts, so thank you very much!

    I haven’t watched your Youtube videos yet, but I think they will be pretty useful in helping the notions sink in. And practice, of course. Always practice! 😀

Leave a Comment