Wave System

Spawn fixed number of enemies based on wave number

Today we will create a wave system. The wave system will decide how many enemies need to be spawned each wave. When those enemies are killed the next wave starts.

New variables

We will need a few new variables to keep track of things:

WaveNumber — to calculate the number of enemies to spawn and to be displayed on the user interface
EnemiesToSpawn — total enemies to spawn this wave based on the wave number
EnemiesLeft — to decide when the wave is completed and to be displayed on the user interface.
We also need a new public method in SpawnManager script to decrease the enemies left from our enemies scripts.
Currently Powerups continue to spawn while enemies are spawning. Let’s change that to spawn while there are more then 0 enemies alive.

Variables Code

//enemy config
[SerializeField] private float _spawnInterval = 3f;
[SerializeField] private GameObject enemyContainer;

[SerializeField] private int[] _enemyWeightTable;
[SerializeField] private GameObject[] _enemyPrefabs;
[SerializeField] private int _enemyWeightTotal = 0;
[SerializeField] private int randomEnemyNumber;

[SerializeField] private float _minPosX, _maxPosX, _startPosY;

//wave config
private int _waveNumber = 0;
private int _enemiesToSpawn = 0;
[SerializeField] private int _ratioWaveEnemies = 1;
private int _enemiesLeft = 0;

private UIManager _uIManager;

private bool _stopSpawning = false;

Wave System Code — Start part

Our WaveNumber starts at zero. When the game starts we start by calling the NextWave(). This increments the wave number and based on the number and the ratio it calculates how many enemies need to be spawned.
We also shorten the spawn interval of enemies with each wave increment. Then we start the spawn routine.

void Start()

private void NextWave()
//start next wave

_enemiesToSpawn = _waveNumber * _ratioWaveEnemies;
_enemiesLeft = _enemiesToSpawn;

//decrease spawn interval each wave
_spawnInterval *= 0.9f;
//calculate total weight
foreach (var weight in _enemyWeightTable)
_enemyWeightTotal += weight;

Wave System Code — Count Enemy Kills

This public method will be called when an enemy is killed.

public void DecreaseEnemiesLeft()
if (_enemiesLeft <= 0)

Wave System Code — Spawn part

Bold parts are the wave system related new parts in the code. It’s a coroutine that keeps spawning from the distribution table while _enemiesToSpawn is larger then zero. Each successful spawn lowers the _enemiesToSpawn.

public void StartSpawning()

IEnumerator SpawnEnemyRoutine()
while (_enemiesToSpawn > 0 && _stopSpawning == false)
randomEnemyNumber = Random.Range(0, _enemyWeightTotal);

for (int i = 0; i < _enemyWeightTable.Length; i++)
if (randomEnemyNumber <= _enemyWeightTable[i])
Vector3 spawnPos = new Vector3(Random.Range(_minPosX, _maxPosX), _startPosY, 0);
GameObject newEnemy = Instantiate(_enemyPrefabs[i], spawnPos, Quaternion.identity);
Debug.Log("SpawnManager: spawining enemy of type: "+_enemyPrefabs[i]+" Time: "+Time.time);
//set parent to container
newEnemy.transform.parent = enemyContainer.transform;
randomEnemyNumber -= _enemyWeightTable[i];
yield return new WaitForSeconds(_spawnInterval);

(PowerupSpawnRoutine is omitted. With the current code each wave starts another PowerupSpawnRoutine is timing is lucky for the player. Could be fixed or could be a feature)

Update UIManager script

We also updated our UIManager script so we can display the wave number and the enemies left etc.

1 Created handles (for wave number text and enemies left text) to assign the new Text Gameobjects through the inspector

2 Initialized the variables in the UIManager script

3 Created public methods to update the UI based on the current number




Aspiring developer that’s self-learning Unity & C# to transition to a career with Unity. I got a passion for creating interactive experiences.

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Why My Variable Always Undefined ? — Learning Python

Poetry: Python package manager for pro projects

Cover image

Coding K8S resource in Java — Part 1 of 2 (K8S API)

Snowball x Spore | New Auto-Compounding Strategies

RemoteHQ 2.0: Multiplayer cloud-based Chrome browser

Announcing Market News Public Beta

Announcing the “Market News” Public Beta

CS373 Spring 2022: Michael Tran

StudioAssistant: A Sinatra-based MVC CMS

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Tristan Engel

Tristan Engel

Aspiring developer that’s self-learning Unity & C# to transition to a career with Unity. I got a passion for creating interactive experiences.

More from Medium

Learn Double Jump in Unity

How to setup Git for a Unity project

Digital Twin as Code (DTaC)

Learn to code by making a 2D space shooter game.