New Feature — Enemy Wave System

Introducing wave after wave of enemies

Jean-Noel Seneque
6 min readJun 30, 2021

Currently, after the asteroid is destroyed, we have the Spawn Manager spawning enemies at a certain rate till the player dies. Not really that exciting. With the new additions of different enemies of various movements, let's work on a wave system that will bring in these enemies and monitor when all the enemies have died before introducing the next set.

Event System

One of the first changes that need to be made in ensuring the Asteroid class is kept clean by staying separate from the Spawn Manager. Currently, the code has a reference to it which means that if we put this class in another project, we will need to bring allow the Spawn Manager which may not make sense in that project. What we really want to do is simply announce the asteroid has been destroyed (an event) and if anything is interesting (subscribed to the event), it will do its thing.

Firstly, we create an event in the Asteroid class

Next, replace the call to the SpawnManager StartSpawning method by fire off the event in the OnTriggerEnter2D method.

We can also comment out of the references in the Asteroid class to the Spawn Manager. It doesn’t need this dependency, it just needs to let interested subscribers know it has exploded.

Let’s create a Wave Manager and subscribe it to listening out for this Asteroid being destroyed event.

Create a WaveManager script with the following code and attach the script to a newly Created Empty object named WaveManager. In it, we will have reference to one enemy to start with.

At the moment, the enemy will start moving downwards as soon as the game starts, we want the enemy to appear only when we tell it too. Drag an enemy into the scene, and un-check it being active. We will enable it in the code when we want it to appear.

Click on the WaveManager and drag the enemy to it.

In the Enemy script, add a Spawn method that we can call that sets the active to true.

In the WaveManager script, create a FirstWave method that will spawn that enemy. Next, create the method that will subscribe to the OnAsteroidDestroyed event that will call the FirstWave method. As soon as the WaveManager starts, it will be that subscription.

If we play the game now, everything works as normal. As soon as the asteroid is destroyed, the event is fired off which enables the enemy to be active.

Now to save on checking for events to save CPU cycles, let’s unsubscribe to the event with the following line after the call to the FirstWave.

Now that is working, let’s change to store not one enemy but a collection of enemies in the WaveManager.

Then we cycle through the array

The Wave Manager is now ready for multiple enemies that are on the scene. Notice how the Inspector Window locked is used to lock it on the WaveManager property so when we can select multiple game objects in the Hierarchy, we don’t have the Inspector Window swap over to a different selected object’s properties.

Play the game now and we have four enemies appearing once the asteroid is destroyed.

Wave Class

Now that is working, let’s create a wave class that encapsulates the wave of enemies.

Create a class named Wave that is Serializable so that customised object appears in the Inspector and move the array and create a new Method called SpawnEnemies.

In the WaveManager script, we have a wave variable and the FirstWave method calls the SpawnEnemies method.

Again drag over the enemies to the collection on the Wave.

The code is now cleaner and is paving what is to come but if you were to play the game now, you wouldn’t notice the difference. We now have an object that represents a single enemy wave. Now that we have a single wave working, let’s turn this into multiple waves but by doing this we need to track when all the enemies in a wave have been destroyed and monitor the state of each wave.

First, let’s add a delay between each wave.

Create a new enum for each of the wave’s states and default the state to waiting and have a getter and setter.

We will have a method to check each of the enemies in a wave are dead

Finally, we will change the Wave Update method to count down a wave using the delay timer, spawn the enemies and then check if the wave is over.

We will now head back to the Wave Manager and change the single wave variable to an array.

Create a variable to track the current wave and set it to the first wave.

When the asteroid is destroyed, we start the first wave by setting its state to active.

Finally, we change the WaveManager’s Update method to update the active wave or move to the next one. Finally if all waves are complete, we are ready for the Boss Enemy to come in (we will work on that later).

This is what Wave Manager looks like in the editor with three waves of enemies.

That draw’s this article to the end. I hope you were able to get something out of this one. Next, I’ll explore a new Power-up that has a negative effect.

If you enjoyed reading this article give me a Clap, also if you would like to see more, “Follow” me, so you may be notified of future releases. You may also send me a message if you need any further help.

--

--

Jean-Noel Seneque

A Data & Analytics Consultant who is expanding into developing experiences in XR, Enterprise and Gaming space using Unity www.jeannoelseneque.com