What is a coroutine?
To put it simple, a coroutine is a control flow mechanism that allows you to pause code execution and resume it at a later time.
In many programming languages, it is implemented as a special kind of function/method that can "yield" control back to the caller. The function can then later be resumed, with the ability to retain its local state, such as variables and function call stack.
Why is it useful?
Coroutines are useful because they enable us to do something during a period of time such as animations or sequences of events.
There are countless ways in which a coroutine can be the perfect solution to a particular problem. A function when called will run to completion and then return control to the calling function along with any optional return values. This means that in our case (game development) any action that takes place inside a function must happen within a single frame update. Coroutines are useful because they enable us to do something during a period of time such as animations or sequences of events.
As examples of the use of coroutines, we could imagine an object that that initiates a rotation after the player interacts with it and then stops after a determined angle is reached. You could of course change rotation for color, distance or whatever else that is possible to change during a time period. As a sidenote, we've also used coroutines for fading music in and out in our adaptive music implementation tutorials such as this one: Implementing Blips music packs in Unity
Coroutine control flow
Coroutines can also be used for performance reasons. Consider a case where we need to check the position of an enemy to determine if it's getting close. If we end up having lots of enemies, calling a function every frame to perform this check can become quite taxing. We can instead consider the use of a coroutine to trigger this check less frequently, like every tenth of a second (100ms) for example, thus freeing up resources for other game systems.
You can also use coroutines to chain events. In a game prototype that I created a few years ago which I named “Outer Cell”, I used multiple coroutines to create a chain of animation events for the playable character (a robot). This robot is controlled by pointing and clicking on the desired location we want it to go (it uses a navigation mesh). Picking up objects in the environment is one of its abilities. When the character is near an interactable object and a command is issued to lift it, the point and click navigation is disabled and both a rotation and a movement coroutine is initiated. The rotation coroutine executes until the robot is facing the object. The movent coroutine gradually moves the robot towards the object and stops as soon as a collision with the object bounds is detected, then a “lift” coroutine starts, raising the robot arms until they reach a horizontal angle to give the player an illusion of carrying the object though a “telekinesis” like kind of power.
Lifting an object in Outer Cell (video game prototype)
Simple code example
Let's have a look at some simple code example using the Unity game engine. Coroutines generally work in a similar way in other engines:
using System.Collections; using UnityEngine; public class ExampleCoroutine : MonoBehaviour { IEnumerator WaitAndPrint() { yield return new WaitForSeconds(3); Debug.Log("Waited for three seconds!"); } void Start() { StartCoroutine(WaitAndPrint()); } }
Here's what this code snippet does:
When entering play mode the Start()
method is called which will initiate the coroutine named WaitAndPrint (In Unity a coroutine is a method declared with an IEnumerator
return type and with a yield return
statement included somewhere in the body). The WaitAndPrint()
method is called just as if we called the method directly but when it reaches the first statement: yield return new WaitForSeconds(3);
it will “yield” pausing the execution and waiting for three seconds before resuming and executing the next statement: Debug.Log("Waited for three seconds!");
which will print the message to the “Console” window.
If familiar with Unity you may be wondering if you couldn't do the same things a coroutine does using the Update()
method, and the answer is yes, you probably could. The difference is that Update runs on every frame and can't be started or stopped, it's always running. In cases where updating every frame is not a concern you would still need to manage the start and stop behaviors by using conditional checks which would end up making your code messy very quickly and difficult to debug, specially if chaining multiple actions like the “Robot interaction” example above.
Conclusion
Coroutines are a powerful and useful tool to employ when developing your game projects. Consider using them whenever you need to execute operations spanning more than one frame or that need to be executed in regular intervals. A coroutine's ability to start, stop and repeat code execution is also one of its benefits.
Do you have any questions or want to share your thoughts with us? Let us know in the comments!