Coroutines and Spawning Objects

Josh Vang
2 min readApr 22, 2021
Sequence Diagram of a Coroutine

Simply put, coroutines are functions that can allow you to start and stop execution of code after certain conditions are met, which are usually part of the YieldInstruction class. As a result, this is really useful when you’re looking to do something that requires a pause. One great example is spawning objects like enemies and power ups. You don’t want it spawn every second, but you do want it to spawn more than once.

Why shouldn’t you use the Update function to spawn objects?

Spawning Enemies using Update function

Of course you can the Update function to spawn objects, in this case enemies as shown above. However, the execution it is more complicated than it looks.

private float _enemySpawnTime = 5.0f;
private float _enemyCanSpawn = -1f;
private GameObject _enemyPrefab;
void Update()
{
if(Time.time > _enemyCanSpawn
{
SpawnEnemy();
}}void SpawnEnemy()
{
Vector3 position = new Vector3(Random.Range(-8,8), 7f, 0f);
_enemyCanSpawn = Time.time + _enemySpawnTime;
Instantiate(_enemyPrefab, position, Quaternion.identity);

}

Sure the code isn’t too complicated, but because we’re spawning the objects in the Update function, it will “infinitly” check that if statement due to the Update function running every frame. As a result, this will add overhead that we can avoid; it might seem fine for now, but when executing multiple Update functions, it can take a toll on the computer. In addition, because we only want the enemy to spawn every 5 seconds, there’s no need to keep checking every frame when executing the code in every 5 seconds is better.

Why you should use coroutines instead?

Using coroutines to spawn objects

Compared to above, using Coroutines to spawn enemies looks similarly to the one when we use the Update function, aside from the power ups being spawned.

And yet, the code is vastly different.

private float _enemySpawnTime = 5.0f;
private GameObject _enemyPrefab;
private bool _canSpawn = true;
void Start()
{
StartCoroutine(EnemySpawn());
}
IEnumerator EnemySpawn()
{
while(_canSpawn)
{
Vector3 position = new Vector3(Random.Range(-8,8), 7f, 0f);
Instantiate(_enemyPrefab, position, Quaternion.identity);
yield return new WaitForSeconds(_enemySpawnTime);
}
}

Not only do we avoid using the Update function entirely, we start the coroutine in the beginning via the Start function. Furthermore, the Coroutine will do the pausing for us; no need to keep checking the current time.

--

--