In this lesson, you will learn how to prevent unnecessary memory allocations in your coroutines to keep your game running smoothly without garbage collection spikes.
The Hidden Cost of "New"
When you write a coroutine that waits for a period of time, it is common practice to write code like this:
IEnumerator MyCoroutine() {
while (true) {
yield return new WaitForSeconds(1.0f);
// Do something...
}
}
While this looks harmless, the new WaitForSeconds(1.0f) instruction creates a new object in memory every single time the loop executes. If this coroutine runs frequently—or if you have dozens of them—Unity’s Garbage Collector (GC) must eventually step in to clear these abandoned objects. This causes those annoying "stutters" or frame drops during gameplay.
The Solution: Caching Yield Instructions
To avoid this overhead, you can "cache" the instruction by creating it once and reusing it. Instead of creating a new object inside the loop, define it as a variable outside the while loop.
Here is the optimized version:
private WaitForSeconds _waitOneSecond = new WaitForSeconds(1.0f);
IEnumerator MyCoroutine() {
while (true) {
yield return _waitOneSecond; // Reuse the existing object
// Do something...
}
}
By storing the instruction in a member variable, you allocate the memory only once when the script initializes. Your coroutine then simply points to that existing memory location during every loop iteration.
Best Practices for Loops
Beyond caching yield instructions, be mindful of what else lives inside your while loops. Avoid creating new strings, lists, or arrays inside the loop, as these allocations also trigger the Garbage Collector. If you need to perform calculations every frame or every few seconds, try to reuse existing variables or pre-allocate data structures outside of the loop whenever possible. By keeping your loop "clean" of new allocations, you ensure that your coroutines remain lightweight and invisible to the Garbage Collector.
Key Takeaway: Stop the Garbage Collector from stuttering your game by caching your yield instructions outside of your coroutine loops rather than creating new objects every iteration.