Unity Guide
Implementing space shooter game features - Enemy behavior
A quick review of new features added to a space shooter game in Unity
Objective: Implement new movement behavior in a space shooter game with Unity.
In the previous post I implemented a new type of shot in my space shooter game with Unity. Now it’s time to implement new movement behavior for the enemies to make the game harder.
New classes
If you have been following my posts, then you’ll remember that we were just using one class to control the enemy behavior. In order to accomplish a new behavior, let’s create new classes, which will use inheritance to make new behaviors scalable and modular when we try to make new enemies in the future.
The new classes will be:
- Enemy
This class won’t inherit MonoBehaviour and it will store the different properties that an enemy could have.
- EnemyBehavior
This class will inherit MonoBehaviour and it will handle the main/simple actions that every enemy could have.
- ForwardEnemy
This class will inherit EnemyBehavior and it will handle enemies that move throughout a line across the space.
Enemy class
First, in the Enemy class, let’s get rid of the MonoBehaviour inheritance and leave just the fields that we need for every type of enemy. Let’s make them public as we’ll modify them through the inspector:
Then, let’s use [System.Serializable] to be able to modify the class in the inspector:
Enemy behavior class
Now, let’s handle the main behavior of the enemies in the EnemyBehavior class. As we are going to be using an animator and audio source component in the enemy, let’s make the class require them with [RequireComponent()]:
Then, let’s create some new variables:
- _enemy
It’s a private Enemy instance. Using [SerializeField] allows us to modify the values from through inspector.
- Speed, XBound & YBound
These are protected properties to let the child classes of this class read the private values from the Enemy instance of this class.
- _canShoot, _dead & _player
These are private variables to manage the main behaviors of the Enemy instance on this class.
Now, let’s make the Start method a public virtual method, so that we can be able to override the function from the child classes of this class. In this case, let’s initialize the values that we need to handle the main behavior of the enemies:
Then, let’s do the same to the Update method. In this case, we need it to handle the shoot feature every certain time:
Finally, let’s just define which functions (that were originally in the Enemy class) work as a main behavior of the enemies:
Forward enemy class
Now, let’s create the first type of secondary enemy behavior, the forward enemy. This type of enemy will move in a single line across the space with different origins (not just from the top, like before).
This class will inherit the EnemyBehavior class to be able to implement the main behavior of any enemy:
Next, let’s create a pair of private variables that will store the bounds of the space from the EnemyBehavior class:
Now, let’s create a function that modifies the transform component values (position & rotation) of the enemy according to the side of the camera where it’s going to be spawned.
We start by choosing a side to spawn with the Random.Range method. Then, we use a switch statement to modify the respective position to spawn by that side of the camera. Finally, we modify the Z rotation of the enemy by calling the GetRandomAngle method with the side selected as a parameter:
The GetRandomAngle method uses this formula to return a random angle between ±45 degrees pointing towards the side of the camera received as a parameter:
Then, let’s initialize the respective variables in the public override Start method, which also calls the Start method from the EnemyBehavior class by using the base.Start method:
Also, like in the method above, let’s make Update a public override method that calls the Update method from the parent class and the MoveEnemy method within this class:
The MoveEnemy method will make sure that the enemy with this script attached will keep moving forward (in a single line) throughout the space in at the speed provided by the protected Speed property from the parent class. Also, it will call the TeleportIfOutOfBounds method form this class:
The TeleportIfOutOfBounds method will call the SetNewTransform method if the enemy reaches the limits of the space, so that it can be teleported with the respective transform values to enter the play field again:
Finally, we’ll be able to attach the ForwardEnemy script to the enemy prefab and modify its values through the inspector to fit our requirements:
If we run the game in Unity, we’ll see that the enemies enter the play field from a different angle and position, making the game harder:
And that’s it, we implemented a new movement behavior! :D. I’ll see you in the next post, where I’ll be showing more features added to my space shooter game in Unity.