Introduction
Coroutines are one of Unity’s most powerful (yet misunderstood) features — and if you’ve ever needed to wait before playing an animation, spawn enemies over time, or create time-based effects without freezing the game, coroutines are the answer.
In this guide, you’ll learn:
- What coroutines are and how they work in Unity
- How to create and start a coroutine
- The difference between coroutines and Update
- Best use cases — and when not to use them
Let’s make your code smarter, cleaner, and more readable
What Is a Coroutine?
A coroutine is a special function in Unity that allows you to pause execution and resume it later — without blocking the main thread.
️ Think of it as:
“Do this thing… wait 3 seconds… then continue doing something else.”
This allows your game to perform delayed or timed operations without freezing or stuttering.
How to Write a Coroutine
A coroutine must:
- Return
IEnumerator - Use the
yield returnkeyword - Be started using
StartCoroutine(...)
IEnumerator WaitAndPrint()
{
Debug.Log("Waiting...");
yield return new WaitForSeconds(2f);
Debug.Log("2 seconds passed!");
}
To start it:
StartCoroutine(WaitAndPrint());
You can place this inside Start() or trigger it via button or event.
⏱️ Unity’s Common Coroutine Yields
| Yield Type | Description |
|---|---|
WaitForSeconds(float) |
Waits for X seconds |
WaitUntil(condition) |
Waits until a condition becomes true |
WaitForEndOfFrame() |
Waits until end of current frame |
WaitForFixedUpdate() |
Waits until next physics step |
null |
Waits until next frame |
Example with WaitUntil:
yield return new WaitUntil(() => enemyDefeated == true);
Example: Spawn Enemies with Delay
Let’s use a coroutine to spawn 5 enemies, one every second.
public GameObject enemyPrefab;
IEnumerator SpawnEnemies()
{
for (int i = 0; i < 5; i++)
{
Instantiate(enemyPrefab, transform.position, Quaternion.identity);
yield return new WaitForSeconds(1f);
}
}
Start it like this:
void Start()
{
StartCoroutine(SpawnEnemies());
}
No Update loop. No timers. Just clean logic.
Coroutine vs Update Loop
| Feature | Coroutine | Update Loop |
|---|---|---|
| Frequency | Runs only when started | Runs every frame |
| Use case | Delayed logic / sequences | Continuous frame logic |
| Syntax | Uses yield return |
Uses conditionals/timers |
| Performance | More efficient for timed logic | Less efficient if misused |
✅ Best Use Cases for Coroutines
- Wait for intro animation to complete
- Time-based damage/heal ticks
- Cooldown timers
- Delayed UI effects (fade-in, popups)
- Spawning objects over time
- Triggering step-by-step story events
❌ When Not to Use Coroutines
- Continuous checks like input or physics
- Critical logic that must execute every frame
- Operations that need precise time control (use
Time.deltaTimeinUpdate)
Advanced Coroutine Tricks
Stop a Coroutine
StopCoroutine("SpawnEnemies");
Or store and stop by reference:
Coroutine spawnRef = StartCoroutine(SpawnEnemies());
StopCoroutine(spawnRef);
Chain coroutines
IEnumerator FirstAction()
{
yield return StartCoroutine(SecondAction());
}
Final Thoughts
Coroutines in Unity offer a simple, clean way to time your logic. Whether it’s for delays, sequences, or conditional waits, coroutines help you write more maintainable and readable code.
Just remember:
- ✅ Use coroutines for timed or delayed logic
- ❌ Don’t use them for every-frame updates
Mastering them will elevate how you structure your gameplay scripts — especially as your projects grow more complex.
Still using messy timers in Update()? Step into the future with coroutines.