Motivation
You should read this tutorial if you are not too sure about coroutines and maybe have had a problem getting them to work the way that you want.
Coroutines are a great way of:
- Making things happen step by step
- Writing routines that need to happen over time
- Writing routines that have to wait for another operation to complete
For example you could easily imagine using a coroutine to orchestrate a cut scene sequence - or simply wait for an enemy to animate dying, pause and then respawn.
Coroutines are a very powerful part of Unity, but they are often much misunderstood by newcomers to the subject. This tutorial will help you get a grip on the power and flexibility of coroutines and understand just how they work.
Threads and Coroutines
First of all lets just be totally clear about this. Coroutines are not threads. Coroutines are not asynchronous.
A thread is a process that runs asynchronously with the other threads in the program. On a multiprocessor machine a thread can really running its code at the same time as all of the other threads. This makes programming threads a complicated thing to get right, because one thread could be changing something at exactly the same time as another thread is reading it. This is even more complicated because the code you write is turned into assembly language by the compiler - which means another thread could actually change something in the middle of the game processing what appears to be a single line of your source code. Because of this you have to go through hoops to ensure that such circumstances don't occur by either making sure that there is no shared memory or by locking other threads out of shared values while they are being read or changed.
Threads will be the subject of a subsequent article.
So What is a Coroutine?
Ok so we've established that a coroutine is definitely not a thread. This means that only one coroutine will be executing at a time and it will be executing on the main thread of the game, so in fact it will be the only thing in the core game code running at that time.
So here is the definition of what a coroutine is:
A coroutine is a function that is executed partially and, presuming suitable conditions are met, will be resumed at some point in the future until its work is done.
Unity processes coroutines every frame of the game for every object that has one or more running. The processing occurs after Update and before LateUpdate for most yield statements, but there are special cases:
When the coroutine is activated it will execute right up to the next yield statement and then it will pause until it is resumed. You can see where it will resume in the diagram above, based on what you yield.
Let's look at a really simple coroutine:
IEnumerator TestCoroutine()
{
while(true)
{
Debug.Log(Time.time);
yield return null;
}
}
This coroutine has a loop that apparently runs forever, it logs the current time and then it yields. When it is resumed, it goes back around the loop, logs the time again and yields once more.
The code inside the loop is exactly like an Update function. It runs once every frame for this object, just after the script's Update routine runs (if it has one).
When you call StartCoroutine(TestCoroutine()) the code executes immediately up to the first time it yields, it will then be resumed when Unity processes coroutines for this object.
Note that this isn't a problem if you make Start or OnCollisionEnter a coroutine, only if you start a coroutine from within them.
To Infinity and Beyond
Now one more thing - the apparently infinite loop in our test coroutine turns out to be not so infinite!
That loop will never execute again if you make a call to stop the coroutines on the game object and it will not run again if the object is destroyed. It will also be paused if the script is disabled directly or by using SetActiveRecursively(false) on the game object.
I Yield Sir
So I made a statement in the last section that you might be questioning. I said:
Unity processes coroutines every frame of the game for every object that has one or more running.
You may be thinking "Oh no it doesn't, what if you use something like yield return new WaitForSeconds(1), then it doesn't process it for another 1 second!"
Well actually Unity does process that coroutine every frame, checking to see if the right amount of time has elapsed - it doesn't process your code, but it does process the coroutine which is the wrapper its made around your script.
So we know that we can effectively pause our code by yielding some value, here's what you can yield:
- null - the coroutine executes the next time that it is eligible
- WaitForEndOfFrame - the coroutine executes on the frame, after all of the rendering and GUI is complete
- WaitForFixedUpdate - causes this coroutine to execute at the next physics step, after all physics is calculated
- WaitForSeconds - causes the coroutine not to execute for a given game time period
- WWW - waits for a web request to complete (resumes as if WaitForSeconds or null)
- Another coroutine - in which case the new coroutine will run to completion before the yielder is resumed
You can also issue the command yield break; which immediately stops the coroutine.
Of course the great thing about all of this is that you can write code that needs to execute over a period of time, or wait for some external event to occur, and keep it all nicely together in a single function making your code far more readable than if you had to write multiple functions or lots of code to keep checking the state of things. That's really the point of coroutines.
Summary
- Coroutines are a really good way of making a sequence of operations happen over time or when some external process is completed
- Coroutines are not threads and are not asynchronous
- Nothing else is running when your coroutine is executing
- Your coroutine will resume when the conditions of your yield statement are met
- Coroutines are inactive when the script is disabled or the object is destroyed
- yield return new WaitForSeconds is dependent on game time which is affected by Time.timeScale
Practical Uses of Coroutines
Hopefully we've established what coroutines are and when they run. Our advanced tutorial will examine the technology behind them.
Let's use coroutines to do something. A couple of simple helper functions can really help us create easy cut sequences using a coroutine.
We can write a coroutine that moves an object to a target location and rotation. We can write a coroutine that waits for an animation to be a certain percentage complete. Then using those two tools we could easily script out a whole cut sequence in a single function where it will be easy to read!
Ensure that you only have one coroutine affecting an object at one time and disable any Update functions that would move the object.
Here's an example of a coroutine to wait for an animation to be partially complete:
//Wait for an animation to be a certain amount complete
IEnumerator WaitForAnimation(string name, float ratio, bool play)
{
//Get the animation state for the named animation
var anim = animation[name];
//Play the animation
if(play) animation.Play(name);
//Loop until the normalized time reports a value
//greater than our ratio. This method of waiting for
//an animation accounts for the speed fluctuating as the
//animation is played.
while(anim.normalizedTime + float.Epsilon + Time.deltaTime < ratio)
yield return new WaitForEndOfFrame();
}
You could write a coroutine to wait for an animation like this:
IEnumerator Die()
{
//Wait for the die animation to be 50% complete
yield return StartCoroutine(WaitForAnimation("die",0.5f, true));
//Drop the enemies on dying pickup
DropPickupItem();
//Wait for the animation to complete
yield return StartCoroutine(WaitForAnimation("die",1f, false));
Destroy(gameObject);
}
The video will show you a lot more and the example project for it is available here.
Video
This video is quite long, but it has some really cool stuff in it! Learn how to build a whole cut sequence using coroutines then see how to apply easing functions to yield statements.
By the end of the video you will know how to build advanced coroutine tools and use them to create great effects. The download for the project has all of the stuff shown in the video.


November 25, 2012 - 3:18 am
very useful, thank you.
in the video you use ToArray() in the foreach statement. could you please explain why?
would the expression (ball != null) otherwise cause problems?
November 25, 2012 - 5:42 am
So firstly the foreach loop is running over quite a period of time – in the previous section of the video I make it so that the balls are destroyed when they fall off the edge, and I remove them from allBalls when that happens.
Now a foreach loop does not like the collection it is iterating over to change, so as we are yielding in it, it is very likely it WILL change due to something being destroyed and removed from the list. To fix that I make a copy of the collection by using .ToArray() – so that just makes a copy of the list when the foreach loop starts, nothing will be removed from that copy. Now that we have a copy the loop is happy – but Unity will be setting the contents of it to null when they are destroyed (its one of those weird useful/unuseful features that are not well documented) – so if the ball has been deleted it will start returning null.
Now here’s a couple of points:
1. When, later in the video, I set timeScale = 0 actually no balls would have been deleted (because they aren’t moving)! I decided to leave it in as belt and braces.
2. We could have taken a single copy of the array and continually used that – but when timeScale was running we might have had a newly spawned ball that wasn’t affected by the later code – again when timeScale became 0 that would not have happened.
I hope that clears it up? Let me know
November 25, 2012 - 9:28 am
yes, all clear. thanks a lot.
November 27, 2012 - 11:41 pm
What do it means by “Nothing else is running when your Coroutine is executing”? As in all other function will not run when Corountine is executing??
November 28, 2012 - 12:39 am
I mean that no other code is running at the same time as your coroutine is in operation. Other code will run when you yield.
January 31, 2013 - 11:40 am
Wonderful and detailed explanation along with a practical example. You have covered most of the nitty-gritty of co-routines. Thx.
February 15, 2013 - 11:16 am
Is it possible to make a co routine wait until a button is pressed before continuing? I’m attempting to do it at the moment, but with no success. This is what I’ve tried;
using UnityEngine;
using System.Collections;
public class example : MonoBehaviour {
public bool check = false;
void Start(){
StartCoroutine(Do());
}
IEnumerator Do() {
SomethingElse();
yield return StartCoroutine(Something());
SomethingElse();
}
IEnumerator Something(){
if (Input.GetButton(“Jump”)){
check = true;
}
while(check == false){
yield return new WaitForEndOfFrame();
}
}
public void SomethingElse(){
print(“Run”);
}
}
February 15, 2013 - 8:01 pm
Hei Chris,
you can simplify the Something function to this:
IEnumerator Something(){
while(!Input.GetKeyDown(KeyCode.Space)){
yield return null;
}
}
I guess it will do what you are expecting. You should get a first print of Run then a second on pressing Space.
The idea is that as long as the Input returns false (notice the ! in front of Input) you will yield and get back to it. Once you press, the Input returns true and you jump over the yield and finish the function that returns to the calling function and all is done.
Fafase
February 16, 2013 - 8:22 am
thanks fafase, it worked like a charm
February 15, 2013 - 8:21 pm
Kind Sir.
This tutorial was most welcome !Thank you
April 15, 2013 - 10:23 am
[...] you’re a coder/scripter and are interested in how coroutines work, Unity Gems has a nice article here which may be off [...]
May 2, 2013 - 1:04 am
Amazing tutorials. Overall UnityGems.
Thanks Mike.
May 11, 2013 - 11:00 pm
Hello Mike,
Thank you for your wonderful tutorials. I am extensively using it for my mobile development.
Being a sole developer, this is just a concern. I am pretty sure there is nothing serious but I wanted to hear it from you.
I use the easing function library extensively and most of the routines look like this.
IEnumerator MoveObject(Vector3 Target, float Timer, EasingType ease = EasingType.Sine, Func EasingFunction = null)
and I call them like this
StartCoroutine(MoveObject(new Vector3(6,0,0), 10f, EasingType.Sine));
So is there any worry I should be having as my target is mobile, you know like garbage like and what not. Right now I am replacing updates with routines.
Thank you.