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;
//handles
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()
{
NextWave();
}
private void NextWave()
{
//start next wave
_waveNumber++;
_uIManager.UpdateUIWave(_waveNumber);
_enemiesToSpawn = _waveNumber * _ratioWaveEnemies;
_enemiesLeft = _enemiesToSpawn;
_uIManager.UpdateUIEnemiesLeft(_enemiesLeft);
//decrease spawn interval each wave
_spawnInterval *= 0.9f; //calculate total weight
foreach (var weight in _enemyWeightTable)
{
_enemyWeightTotal += weight;
} StartSpawning();
}
Wave System Code — Count Enemy Kills
This public method will be called when an enemy is killed.
public void DecreaseEnemiesLeft()
{
_enemiesLeft--;
_uIManager.UpdateUIEnemiesLeft(_enemiesLeft);
if (_enemiesLeft <= 0)
{
NextWave();
}
}
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()
{
StartCoroutine(SpawnEnemyRoutine());
StartCoroutine(SpawnPowerUpRoutine());
}
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);
_enemiesToSpawn--;
//set parent to container
newEnemy.transform.parent = enemyContainer.transform;
break;
}
else
{
randomEnemyNumber -= _enemyWeightTable[i];
}
}
_uIManager.UpdateEnemiesToSpawn(_enemiesToSpawn);
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