Course contentsShow
← Unity Game Development
Lesson 137 of 8282. Scripting and LifecycleFree lesson

Managing Coroutine State Across Scene Changes

Prevent memory leaks and logic errors by correctly stopping active coroutines when objects are destroyed or scenes are transitioned.

In this lesson, you will learn how to prevent dangling coroutines from causing memory leaks or errors when your game shifts from one scene to another.

The Scene Transition Trap

When you load a new scene in Unity, any objects that were not marked with DontDestroyOnLoad are destroyed. While Unity automatically stops coroutines attached to a MonoBehaviour that is destroyed, issues often arise if your coroutine is running a reference to a long-lived manager or if you are using static references.

A common logic error occurs when a coroutine attempts to modify an object (like updating a UI element) that no longer exists in the current scene. This results in "MissingReferenceException" errors. To manage state effectively, you must understand that the lifecycle of a coroutine is bound to the GameObject that started it.

Stopping Coroutines Safely

To keep your project clean, you should explicitly stop any running background tasks before a scene transition if those tasks rely on local scene data. Here is a simple pattern to ensure you aren't leaving "ghost" processes running:

public class SceneTaskHandler : MonoBehaviour
{
    private Coroutine _myTask;

    void Start() {
        _myTask = StartCoroutine(DoWork());
    }

    // Call this manually before changing scenes
    public void StopTasks() {
        if (_myTask != null) {
            StopCoroutine(_myTask);
            _myTask = null;
        }
    }

    private IEnumerator DoWork() {
        while (true) {
            // Logic that relies on current scene objects
            yield return new WaitForSeconds(1f);
        }
    }
}

Why This Matters

If you trigger a scene load while a coroutine is midway through an IEnumerator chain, the coroutine might attempt to perform a final action or log a result once it resumes. If it checks for this.gameObject or any cached scene components, it will fail. By manually stopping these coroutines during a cleanup phase—or by ensuring that objects carrying persistent logic are kept outside of the transient scene hierarchy—you keep your memory footprint stable and your console free of transition-related errors.

Key Takeaway: Always explicitly stop coroutines that rely on scene-specific objects before transitioning to a new scene to prevent memory leaks and orphaned execution logic.