【Unity】Mastering Coroutines: Unity's Asynchronous Processing

Created: 2025-12-07

Need to wait a few seconds before resuming? Want to split heavy processing across frames? Learn Unity's powerful Coroutine feature with IEnumerator and yield return explained for beginners.

Overview

When developing games in Unity, you'll frequently encounter scenarios like: "spawn an enemy after 3 seconds," "fade out when a button is pressed," or "split heavy loading across multiple frames to prevent freezing."

Implementing such time-based or heavy processing with regular functions becomes very complex. Unity provides Coroutines—a powerful feature that makes writing such asynchronous-like processing remarkably simple. This article covers the fundamentals of coroutines, focusing on IEnumerator and the yield return keyword.

What are Coroutines?

Coroutines are special functions that can pause execution temporarily and resume later at a specific time. While regular functions must execute to completion once called, coroutines can return control to Unity mid-execution with instructions like "resume next frame" or "resume in 5 seconds."

This enables intuitive implementation of time-based events and processing splits without complicating your Update function.

Basic Coroutine Usage

Implementing coroutines requires three elements:

  1. Function returning IEnumerator type: This is the coroutine body. IEnumerator is a standard C# interface meaning "enumerable."
  2. yield return: The keyword that pauses coroutine execution and returns control to Unity. Specify resume conditions after this.
  3. StartCoroutine(): The method to start your coroutine.

Time-Waiting Coroutine

The most basic usage waits for a specified time before resuming. Use yield return new WaitForSeconds(float seconds).

using System.Collections;
using UnityEngine;

public class CoroutineExample : MonoBehaviour
{
    void Start()
    {
        Debug.Log("Starting coroutine.");
        // Start coroutine using method name as string
        StartCoroutine("WaitAndPrint");
    }

    // Define coroutine as IEnumerator-returning function
    IEnumerator WaitAndPrint()
    {
        // Pause execution for 3 seconds
        yield return new WaitForSeconds(3.0f);

        // Execution resumes here after 3 seconds
        Debug.Log("3 seconds have passed!");
    }
}

Running this script displays "Starting coroutine." immediately, then "3 seconds have passed!" three seconds later. The Start function completes right after starting the coroutine, but the coroutine continues waiting in the background and resumes when the specified time elapses.

Various Pause Conditions with yield return

Beyond WaitForSeconds, various pause/resume conditions can follow yield return:

After yield returnResume Timing
nullResumes before next frame's Update is called
new WaitForEndOfFrame()Resumes right after frame rendering completes (end of that frame)
new WaitForFixedUpdate()Resumes just before next FixedUpdate
StartCoroutine(AnotherCoroutine())Resumes after AnotherCoroutine fully completes. Enables nested coroutines.

yield return null; is commonly used for splitting heavy processing:

IEnumerator HeavyProcess()
{
    for (int i = 0; i < 10000; i++)
    {
        // Heavy calculation
        DoSomethingHeavy(i);

        // Wait 1 frame every 100 iterations
        if (i % 100 == 0)
        {
            Debug.Log(i + " iterations processed. Taking a 1-frame break.");
            yield return null; // Pause here, resume next frame
        }
    }
}

Stopping Coroutines

Started coroutines can be stopped mid-execution. To stop a coroutine, save StartCoroutine's return value in a Coroutine variable and pass it to StopCoroutine.

using System.Collections;
using UnityEngine;

public class StoppableCoroutine : MonoBehaviour
{
    private Coroutine myCoroutine;

    void Start()
    {
        Debug.Log("Starting coroutine that executes something in 10 seconds.");
        myCoroutine = StartCoroutine(LongProcess());
    }

    void Update()
    {
        // Stop coroutine when C key is pressed
        if (Input.GetKeyDown(KeyCode.C))
        {
            if (myCoroutine != null)
            {
                Debug.Log("Coroutine cancelled.");
                StopCoroutine(myCoroutine);
                myCoroutine = null; // Clear reference after stopping for safety
            }
        }
    }

    IEnumerator LongProcess()
    {
        yield return new WaitForSeconds(10f);
        Debug.Log("10 seconds passed! Processing executed.");
    }
}

StopAllCoroutines() stops all running coroutines on that script at once.

Summary

Coroutines are fundamental to asynchronous processing in Unity—master them to write expressive logic simply.

  • Coroutines are special functions that can pause and resume execution.
  • Return IEnumerator, pause with yield return.
  • Start with StartCoroutine(), stop with StopCoroutine().
  • new WaitForSeconds(t) for time waits, null for 1-frame waits are the basics.

Time-based effects, AI thinking routines, splitting heavy processing—coroutines have infinite applications. Start with simple time waits to experience their convenience.