Coroutines
A coroutine allows you to spread tasks across several frames. In Unity, a coroutine is a method that can pause execution and return control to Unity but then continue where it left off on the following frame.
In most situations, when you call a method, it runs to completion and then returns control to the calling method, plus any optional return values. This means that any action that takes place within a method must happen within a single frame update.
In situations where you would like to use a method call to contain a procedural animation or a sequence of events over time, you can use a coroutine.
However, it’s important to remember that coroutines aren’t threads. Synchronous operations that run within a coroutine still execute on the main thread. If you want to reduce the amount of CPU time spent on the main thread, it’s just as important to avoid blocking operations in coroutines as in any other script code. If you want to use multi-threaded code within Unity, consider the C# Job System.
It’s best to use coroutines if you need to deal with long asynchronous operations, such as waiting for HTTP transfers, asset loads, or file I/O to complete.
Coroutine example
As an example, consider the task of gradually reducing an object’s alpha (opacity) value until it becomes invisible:
In this example, the Fade method doesn’t have the effect you might expect. To make the fading visible, you must reduce the alpha of the fade over a sequence of frames to display the intermediate values that Unity renders. However, this example method executes in its entirety within a single frame update. The intermediate values are never displayed, and the object disappears instantly.
To work around this situation, you could add code to the Update function that executes the fade on a frame-by-frame basis. However, it can be more convenient to use a coroutine for this kind of task.
In C#, you declare a coroutine like this:
A coroutine is a method that you declare with an IEnumerator return type and with a yield return statement included somewhere in the body. The yield return null line is the point where execution pauses and resumes in the following frame. To set a coroutine running, you need to use the StartCoroutine function:
The loop counter in the Fade function maintains its correct value over the lifetime of the coroutine, and any variable or parameter is preserved between yield statements.
Coroutine time delay
By default, Unity resumes a coroutine on the frame after a yield statement. If you want to introduce a time delay, use WaitForSeconds:
You can use WaitForSeconds to spread an effect over a period of time, and you can use it as an alternative to including the tasks in the Update method. Unity calls the Update method several times per second, so if you don’t need a task to be repeated quite so often, you can put it in a coroutine to get a regular update but not every single frame.
For example, you can might have an alarm in your application that warns the player if an enemy is nearby with the following code:
If there are a lot of enemies then calling this function every frame might introduce a significant overhead. However, you could use a coroutine to call it every tenth of a second:
This reduces the number of checks that Unity carries out without any noticeable effect on gameplay.
Stopping coroutines
To stop a coroutine, use StopCoroutine and StopAllCoroutines. A coroutine also stops if you’ve set SetActive to false to disable the GameObject The fundamental object in Unity scenes, which can represent characters, props, scenery, cameras, waypoints, and more. A GameObject’s functionality is defined by the Components attached to it. More info
See in Glossary the coroutine is attached to. Calling Destroy(example) (where example is a MonoBehaviour instance) immediately triggers OnDisable and Unity processes the coroutine, effectively stopping it. Finally, OnDestroy is invoked at the end of the frame.
Note: If you’ve disabled a MonoBehaviour by setting enabled to false , Unity doesn’t stop coroutines.
Analyzing coroutines
Coroutines execute differently from other script code. Most script code in Unity appears within a performance trace in a single location, beneath a specific callback invocation. However, the CPU code of coroutines always appears in two places in a trace.
All the initial code in a coroutine, from the start of the coroutine method until the first yield statement, appears in the trace whenever Unity starts a coroutine. The initial code most often appears whenever the StartCoroutine method is called. Coroutines that Unity callbacks generate (such as Start callbacks that return an IEnumerator ) first appear within their respective Unity callback.
The rest of a coroutine’s code (from the first time it resumes until it finishes executing) appears within the DelayedCallManager line that’s inside Unity’s main loop.
This happens because of the way that Unity executes coroutines. The C# compiler auto generates an instance of a class that backs coroutines. Unity then uses this object to track the state of the coroutine across multiple invocations of a single method. Because local-scope variables within the coroutine must persist across yield calls, Unity hoists the local-scope variables into the generated class, which remain allocated on the heap during the coroutine. This object also tracks the internal state of the coroutine: it remembers at which point in the code the coroutine must resume after yielding.
Because of this, the memory pressure that happens when a coroutine starts is equal to a fixed overhead allocation plus the size of its local-scope variables.
The code which starts a coroutine constructs and invokes an object, and then Unity’s DelayedCallManager invokes it again whenever the coroutine’s yield condition is satisfied. Because coroutines usually start outside of other coroutines, this splits their execution overhead between the yield call and DelayedCallManager .
You can use the Unity Profiler A window that helps you to optimize your game. It shows how much time is spent in the various areas of your game. For example, it can report the percentage of time spent rendering, animating, or in your game logic. More info
See in Glossary to inspect and understand where Unity executes coroutines in your application. To do this, profile your application with Deep Profiling enabled, which profiles every part of your script code and records all function calls. You can then use the CPU Usage Profiler module to investigate the coroutines in your application.
Profiler session with a coroutine in a DelayedCall
It’s best practice to condense a series of operations down to the fewest number of individual coroutines possible. Nested coroutines are useful for code clarity and maintenance, but they impose a higher memory overhead because the coroutine tracks objects.
If a coroutine runs every frame and doesn’t yield on long-running operations, it’s more performant to replace it with an Update or LateUpdate callback. This is useful if you have long-running or infinitely looping coroutines.
Unity Coroutine, simple guide with code samples
Unity Coroutine gives you the power to pause and resume code blocks at your disposal. You can decide how the execution of code is to be done and which code needs to wait. You can execute the coroutine in a way to optimize your game’s performance. In this post, we will see what is a Coroutine and how to start and stop a coroutine along with examples, advantages and disadvantages.
As you can see, inside the Start function, we start the coroutine and then print “Complete!”. When the coroutine started it waited for 3 seconds (because that’s the amount we passed through the parameter), and then instantiated a Gameobject. Then it waited for 2 additional seconds and printed another message stating that it spawned Cube after 5 seconds. It says 5 seconds because that is the amount of time that has passed since the game started (3 + 2 seconds). we got the Time by using Time.time, which is a variable that returns the amount of time since the game started.
If you are planning to use the same delay multiple times then you can improve the performance of the WaitForSeconds function using a variable. Here is how to do it
We have another problem!
Inside the start function, we printed “Complete!”, but the coroutine is not complete yet. Let’s fix that in this coming section y waiting for the Coroutine to finish.
Waiting for Coroutine to finish
In order to wait for a coroutine to finish processing before we can move on, we need to yield from the place that we are calling the coroutine and the function from which we are starting the Coroutine should also be a Coroutine. Here’s an example:
We converted the start function into a Coroutine with a return type IEnumerator and added the keywords yield return before we started the coroutine. Yield as we mentioned, is what tells unity to move on to the next frame. So, until the SpawnBoxAfterSeconds Coroutine hasn’t been completed, we do not move on to the next line. Note that this could cause the game to get stuck in an infinite loop if not written correctly.
Below is the result of the above code. As you can see, “Complete!” gets called right after the cube is spawned.

WaitForSeconds is affected by Time.timescale in Unity. If you want the Coroutine to run even when the timescale is set to zero then you can use the function below.
This uses the system time and is not affected by change in time in Unity.
Make Unity Coroutine Wait Until a condition is true
You can use WaitUntil method to pause a Coroutine in Unity till a condition is met. WaitUntill takes a Boolean as input parameter and pauses the Coroutine until the parameter is true.
Here is how to use it
Make Unity Coroutine Wait While a condition is true
WaitWhile is very similar to WaitUntil. The Difference between them is WaitUntil will pause till the parameter is false whereas WaitWhile will pause when the parameter is true.
Here is how to use WaitWhile
Make Coroutine wait till end of frame
You can make the Coroutine wait till the end of the current frame using the function WaitForEndOfFrame.
Here is a code sample
Make Coroutine wait will next frame
As you have seen in the above examples you can pass many functions to the yield statement depending on how you want the Coroutine to wait before proceeding. If you want the Coroutine to just wait till the next frame then you can pass null to the yield statement.
Here is how to use it
Making a timer with coroutine
You can implement a Unity timer with Unity Coroutine with much ease. Coroutines are useful to execute a function over a number of frames. The main difference between using a coroutine and normal time.deltatime is displaying time. If you want to display a timer that changes every frame then it’s better not to use a coroutine. But if you want to execute a function after a time period then coroutine is the easiest way.
One other important thing to note is coroutine can be used only with MonoBehaviour. If you are looking to make a Unity timer without MonoBehaviour then use the first method.
Creating the script
- Create a new script callled Waitforsecond_unity.
- Copy and paste the code below into the script.
- Set the required time in the delay variable.
- Click play the value of ammo variable will set to 50 after 5 seconds.
If you are using the yield statement then the return type should be IEnumerator.
Advantages and Uses of Unity Coroutine
Coroutines are mainly used, when necessary, rather than for convenience. It is easy to use, and it’s quite handy in many situations. However, the sad truth is that coroutines are expensive when overused or when not tracked. Make sure that your coroutines always end. And if they do not work in a way that they end when a condition is satisfied (maybe you want to constantly calculate something all the time), then stop the coroutines manually through code yourself. Cleanup is very important when using a lot of coroutines.
What Is an IEnumerator In C# and what is it used for in Unity?
I read the documentation but couldn’t understand it..
![]()
2 Answers 2
what is the use of IEnumerator function
IEnumerator there isn’t a function, it’s a return type. C# doesn’t have functions either (but I know what you mean) — in C# we call them methods.
IEnumerator being so called implies it is an interface, so any class that implements the IEnumerator interface can be returned by this method
In practice in this use it seems that it’s actually more of a hack than intending to provide the true intent of an enumerator, which is to step-by-step rifle through(or generate) a collection of things.
When you use a yield return statement within a method "some magic happens" whereby it’s not a return in the classic sense, but creates a facility whereby the code can resume from where it left off (calling for the next item out of the returned enumerator will cause the code to resume from after the yield, with all the state it had before, rather than starting over).
If you look at the MSDN example for yield:
The loop is controlled by i ; if this wasn’t a yield return then this wouldn’t function as intended (it couldn’t return an enumerator for a start but we’ll leave that out). Suppose it was just a normal return , the loop would never loop at all; the code would enter, start the loop, hit the return , and just return a number one time and all memory of where the loop was would be forgotten.
By making it a yield return , an enumerator is returned instead, and a small set of "saved state" is set up whereby the loop can remember the current value of i — each time you ask for the next value, the code resumes where it left off from (ie just after the yield), the loop goes round again and a different value is yielded. This continues up to the max of course.. at which point the returned enumerator says it has no more items
You could yield forever, too.. If the code can never escape the loop then it will yield/generate forever
In this case you have to use yield return new WaitForSeconds because that’s how WaitForSeconds is intended to work. Yielding gives up an enumerator to the calling method, which is then free to enumerate it. From the docs it looks like this is deliberately done on the next frame, so using yield (perhaps repeatedly) is a way of arranging a block of code that occurs across several frames without having some sort of external state management that remembers where the process is up to and a wordy
- if state = 1 then close the door and add 1 to the state,
- else if state = 2 then light the torch and add 1
- else if state = 3 . ".
- yield,
- close the door,
- yield,
- light the torch,
- yield ..
Can’t we do this by this process
Sure, looks reasonable; look at the clock 100 times a second and if 0.5 seconds have passed since you first looked at the clock, spawn the obstacles
I’d imagine (never used Unity; don’t profess to know anything about it other than having read the docs for this one function) that your Update loop has a lot more to be getting on with, so handing a process off to a dedicated wait-then-do is more efficient than spending all your time looking at a clock and carrying out a potentially complicated calc to work out if you should do something; most things in life that start out as poll-every-x-milliseconds benefit from being switched to an "if the event occurs, react to it" way of working
How do Unity’s coroutines actually work?
Coroutines in Unity are a way to run expensive loops, or delays in execution, without having to involve multithreading. That’s right – although it’s commonly believed that coroutines are multithreaded operations, they in fact run on the main thread. But have you ever asked yourself why coroutines return IEnumerator ? What does that even mean? We’ll take a look at how they work, and I hope to explain just how genius they are.
Coroutines are not multithreading
You can prove this to yourself by calling Thread.Sleep from within a coroutine.
Attach this behaviour to a game object, and you will see that execution sleeps for 5 seconds on the current thread – which is the main thread. The game freezes entirely. If coroutines ran on a separate threads, this Sleep call would not interfere with rendering.
What does it mean to yield ?
Let’s backpedal from Unity and start a blank Console Application, and explain what makes the yield keyword so special.
Let’s define a method which returns IEnumerable<int> called GetNumbers . This method will allocate a list and then loop 10 times. In the loop we will add the current loop iteration to the list, and then Thread.Sleep for 1 second. Afterwards, we will return the list.
We can then call this method and iterate through its return value using a foreach loop, outputting each element to the console.
Running this code, you will notice something. It waits 10 seconds before finally outputting the values 1-10 immediately, all at once. This is because in order to foreach over a collection, it has to know what that collection is. But it can only know what the collection is once the method returns. But the method only returns once its for loop is complete, which means it has to Thread.Sleep 10 times, 1 second each, adding each element to the list before the method finally gives the result back to the caller: our foreach .
Now let’s adjust our code. We’ll remove the creation of the list, and the return statement at the end. Instead having a yield return statement inside the loop. We will return the value of iterator . The GetNumbers method now looks like this:
The foreach loop in Main does not need to be touched – we still want to iterate over the result of this method. Except, running this code, you will immediately see the difference this made.
Instead of sleeping 1 second – 10 times – before finally returning control back to the caller (leading to a 10 second sleep in total), what we are doing is quite literally “yielding” control back to the caller with the next value of iterator in every iteration of the for loop. This gives a chance for the foreach body to execute, print the value, and then return back to GetNumbers to essentially ask “what next?” – at which point the current thread Sleep s for 1 second, and the for loop continues to the next value.
Wait. That’s an IEnumerable . Unity uses IEnumerator !
Correct it does! IEnumerable is the base interface for all things that are – well – “enumerable”. Lists, arrays, queues, stacks, dictionaries, anything which can be enumerated implements IEnumerable . IEnumerator , on the other hand, is a type which is responsible for defining how these enumerables should be enumerated.
In short, IEnumerable is a collection of values. IEnumerator is responsible for iterating over such collections.
Let’s get our hands dirty and see what this actually means.
Diving deep into how foreach works
You may have noticed that types such as arrays and lists all define a GetEnumerator method. This method returns a type which implements IEnumerator responsible for implementing the way that the current collection must be enumerated.
Save for arrays, because those compile slightly differently, a foreach actually compiles to a while loop which runs for as long as IEnumerator.MoveNext returns true . You can see this in action here!
Ignoring the initialisation and try-catch , our source code:
… compiles to this:
What is actually happening here, and why does it work?
We can browse the .NET source code for the List<int>.Enumerator struct to see what’s going on. Let’s remove all the noise, clean it up so it’s more readable, and just focus on the important parts.
We see that the enumerator tracks the current index, as well as the value at that index. The Current property just returns the value of the _current field. But every call to MoveNext checks if the index is within the bounds of the list. If it is, it assigns _current to the value at _index , increments _index , and returns true .
So the while loop we saw above is simply asking the enumerator to move to the next index, and then accesses Current . Until, of course, _index reaches the end of the list, at which point it returns false and the loop is complete.
A Stack<T> enumerator behaves a similar way, except it iterates backwards. Looking at the source code for StackEnumerator , line 361 shows a decrement: —_index . This is the reason a foreach calls GetEnumerator – because different collection types need to be enumerated differently.
What does this have to do with coroutines?
Whenever you call StartCoroutine , Unity adds the IEnumerator to a collection of coroutines on which it needs to call MoveNext in every iteration of its own game loop. We can see this in action if we were to create our own yield instruction in Unity. Below is an example of a custom WaitForTime – which accepts a TimeSpan rather than a float for seconds.
The constructor calculates the end time by adding the TimeSpan parameter to the current time. Then in MoveNext , we simply check whether or not the current time has elapsed the end time. It returns true for as long as _endTime is in the future.
If we yield return a new instance of this in a coroutine, it works as expected:
We can shove in a few Debug.Log calls to see when Unity is calling things.
You can see the message count for the MoveNext call shoots up to the thousands extremely quickly.
No, seriously, coroutines are not multithreading
Despite the names of the types – WaitForSeconds , WaitForSecondsRealtime , WaitForEndOfFrame , and our very own WaitForTime – containing the word “wait”, there’s no actual waiting going on here; MoveNext is called every single frame and there is zero pause between each call (we can see evidence of that in our Console). The only reason there is an apparent pause before “Slept for 5 seconds!” is logged is because of the yield . We constantly yield control back to Unity’s game loop, and so long as our instruction’s MoveNext returns true , control never continues beyond that point. At no point do Wait instructions hang the thread. There is no Thread.Sleep call.
As an aside, that means – if you really wanted to, you could create an endless instruction which “waits” forever, just by defining MoveNext to unconditionally return true .
Conclusion
I was planning to write up a small example project which implemented a system very similar to Unity’s coroutines to demonstrate how Unity’s game loop actually handles them. While I did get it working, the code ended up being far more long-winded than I originally anticipated. Frankly, this makes me respect coroutines even more; I underestimated the level of wizardry that they involved. So much so that I felt it went far beyond the scope of this article.
However! If enough of you are interested in another post in which I elaborate on that code, perhaps I’ll write about it in future. Let me know in the comments.
While coroutines have their pitfalls – and trust me there are many – they certainly are a very clever feature. One which I feel is often underappreciated.