Coroutines let you write logic that spans multiple frames in a straight-line style, without callbacks or state machines. You write a normal C# method that returnsDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/ProwlEngine/Prowl/llms.txt
Use this file to discover all available pages before exploring further.
IEnumerator, then yield control back to the engine at any point — for a set duration, until the end of the current frame, or until the next physics step. The engine resumes your method exactly where it left off on the next eligible frame. This makes coroutines ideal for timed sequences, loading stages, animation orchestration, and any behavior that “happens over time” but is too simple to warrant a full state machine.
How Coroutines Work
A coroutine is started withStartCoroutine(string methodName) — passing the name of a method on the same MonoBehaviour that returns IEnumerator. The engine uses reflection to locate the method by name, invokes it, and wraps the resulting IEnumerator in a Coroutine object that advances each frame (or each fixed step, depending on the yield instruction in use).
Coroutines are tracked by method name inside three separate internal dictionaries:
- Default — advances once per
Update()frame. - End-of-frame — advances after all cameras and GUI have rendered (
WaitForEndOfFrame). - Fixed-update — advances on physics ticks (
WaitForFixedUpdate).
IEnumerator is exhausted), it is automatically removed. You can also stop one explicitly by name.
Starting Coroutines
The method name passed to
StartCoroutine(string) must exactly match the name of a method on the same MonoBehaviour instance (public or private). The engine uses reflection to locate it; a typo produces a runtime error message and returns null.Stopping Coroutines
StopCoroutine(string methodName) removes the coroutine from all three internal queues (default, end-of-frame, and fixed-update). StopAllCoroutines() clears every queue at once.
Yield Instructions
Prowl provides three built-in yield instructions, all inheriting fromMonoBehaviour.YieldInstruction.
WaitForSeconds
Suspends the coroutine until
seconds of scaled game time have elapsed. Stores the target end-time (Time.time + seconds) at construction.WaitForEndOfFrame
Suspends until after all cameras and GUI have rendered for the current frame, just before the frame is displayed.
WaitForFixedUpdate
Suspends until the next physics fixed-update tick. Useful for physics queries that must run in-step.
WaitForSeconds
WaitForSeconds captures Time.time + seconds at construction as the target end-time. Because it uses scaled time, pausing the game (Time.timeScale = 0) will also pause any pending WaitForSeconds yields.
WaitForEndOfFrame
WaitForFixedUpdate
Chaining Coroutines
You can yield on anotherCoroutine object to wait for it to finish before continuing. Coroutine itself extends YieldInstruction, so the engine knows to pause the outer coroutine until the inner one completes.
Practical Examples
- Delayed Action
- Animation Sequence
- Loading Sequence
- Repeating Timer
Important Gotchas
Coroutines stop when disabled
If the GameObject or MonoBehaviour is disabled or destroyed mid-coroutine, the coroutine is silently abandoned. Always restart them in
OnEnable if the behavior should resume.Scaled time pauses WaitForSeconds
WaitForSeconds uses Time.time, which is affected by Time.timeScale. Setting timeScale = 0 to pause the game will also freeze all pending WaitForSeconds yields.Starting a duplicate name throws
Coroutine names are stored as dictionary keys per
MonoBehaviour instance. Starting a coroutine whose method name is already running will throw a runtime exception. Call StopCoroutine first if you need to restart one.Coroutines are not threads
Coroutines run on the main thread between frames. They cannot do parallel work. For CPU-heavy tasks that must not block rendering, use
System.Threading.Tasks.Task or async/await instead.Coroutines vs Task / async-await
| Concern | Coroutine | Task / async-await |
|---|---|---|
| Multi-frame game logic | ✅ Natural fit — yields integrate with frame loop | ❌ Requires marshalling back to main thread |
Time paused by timeScale | ✅ WaitForSeconds respects scale | ❌ Task.Delay uses wall-clock time |
| CPU-heavy background work | ❌ Blocks the main thread | ✅ Runs on thread pool |
| I/O (file, network) | ❌ Awkward — must await from Update | ✅ First-class support |
| Exception propagation | ❌ Swallowed silently | ✅ Full stack trace via await |
async/await for I/O, heavy computation, or any scenario where you need a real thread.