Write and run coroutines
Write and run coroutine methods to do work that takes effect over several frames, such as a gradual fade-out effect.
Read time 5 minutesLast updated 12 days ago
A coroutine is a method that can suspend execution and resume at a later time. In Unity applications, this means coroutines can start running in one frame and then resume in another, allowing you to spread tasks across several frames.
Regular, non-coroutine methods run to completion before returning control to the caller, which in the Unity runtime means their action completes within a single frame update. In situations where you want the work of a method to take effect over several frames, such as a gradual fade-out effect, you can use a coroutine. Coroutines are also useful for handling long asynchronous operations, such as waiting for HTTP transfers, asset loads, or file I/O to complete.
- The job system
- The .NET async and await and Unity's custom support
Awaitable
Writing coroutines
Consider the task of gradually reducing an object's alpha (opacity) value until it becomes invisible. For the fading effect to be visible, the opacity must reduce over a sequence of frames. If you tried to write a method, you might write something like the following:
Fadevoid Fade(){ Color c = renderer.material.color; for (float alpha = 1f; alpha >= 0; alpha -= 0.1f) { c.a = alpha; renderer.material.color = c; }}
This method is not a coroutine, so it executes every iteration of its loop within a single frame update and the object disappears instantly instead of appearing to fade out. One posible solution is to add code to the function that executes the fade on a frame-by-frame basis. However, it can be more convenient to use a coroutine.
forUpdateCoroutines are methods with an return type and a yield return statement included somewhere in the body. The statement is the point at which execution is suspended. The previous method can be rewritten as a coroutine as follows:
IEnumeratoryield returnFadeIEnumerator Fade(){ Color c = renderer.material.color; for (float alpha = 1f; alpha >= 0; alpha -= 0.1f) { c.a = alpha; renderer.material.color = c; yield return null; }}
This version of the method executes one iteration of its loop before suspending execution at the statement. It resumes and executes another iteration of the loop in the next frame, and so on, making the gradual fade effect visible. The loop counter in the method maintains its correct value over the lifetime of the coroutine, and any variable or parameter is preserved between statements.
foryield return nullFadeyieldStarting and stopping coroutines
To set a coroutine running, use the StartCoroutine method:
void Update(){ if (Input.GetKeyDown("f")) { StartCoroutine(Fade()); }}
To stop a coroutine, use StopCoroutine and StopAllCoroutines. A coroutine also stops if:
- The value of becomes
GameObject.activeSelffor the GameObject the script is attached to.false - The MonoBehaviour script is destroyed with a call to Destroy.
Resuming coroutines
When a suspended coroutine resumes execution depends on the yield instruction provided in the statement. A resumes on the next frame. Unity has a set of custom yield instructions that you can use to resume after a specified time, when a specified conditions is met, or at specific points in the Player loop. For more information, refer to Yield instruction reference.
yield returnyield return nullIn the case of fade effect example, you might want the fade effect to happen at a lower and more consistent rate than the frame rate. You can the instruction to introduce a fixed time delay between iterations of the method as follows:
yield returnWaitForSecondsFadeIEnumerator Fade(){ Color c = renderer.material.color; for (float alpha = 1f; alpha >= 0; alpha -= 0.1f) { c.a = alpha; renderer.material.color = c; // Wait for 0.1 seconds before the next iteration yield return new WaitForSeconds(.1f); }}
It's also possible to a Unity from within a coroutine. This can be useful if you want to integrate coroutines with asynchronous code that uses and . For example, in the previous example you could instead of to achieve the same effect.
yield returnAwaitableasyncawaityield return Awaitable.WaitForSecondsAsync(.1f)yield return new WaitForSeconds(.1f)Coroutines in Edit mode
Coroutines are primarily a runtime feature. The associated runtime yield instructions are in the namespace and run in the Editor's Play mode or in a standalone platform Player. They can also run in Edit mode if your scripts use the or attributes, but the update loop in Edit mode is not as fixed and regular as the Player loop.
UnityEngine[ExecuteInEditMode][ExecuteAlways]For coroutines designed specifically to run in Edit mode, use the Editor coroutines package.
Coroutines in tests
Unity Test Framework Play mode tests marked with the attribute run as coroutines and allow you to yield custom instructions for the Unity Editor from tests. For more information, refer to Yield instructions for the Editor.
[UnityTest]Coroutine performance
Coroutines can cause hidden allocations and garbage collector spikes if misused. Each coroutine creates an state machine. Starting them frequently (for example, per frame) allocates and adds overhead. A does not allocate but yield instructions like do. Cache commonly reused ones and avoid lambdas in and to prevent delegate and capture allocations.
IEnumeratoryield return nullnew WaitForSecondsWaitUntilWaitWhilePrefer long-lived coroutines that loop with instead of repeatedly starting new ones. Cache or pool with fixed durations. Coroutines retain references to their owner and captured variables. Ensure they end or are stopped with to avoid leaks.
yield return nullWaitForSecondsMonoBehaviour.StopCoroutineAlways profile, especially on constrained platforms, to confirm and locate allocations. For more information, refer to Analyzing coroutines.