New Enemy Detected — Enemy Types and Behaviors

Jack Leavey
4 min readJun 12, 2022

--

In the example game, the base experience is intact, but there is only one threat to the player; a single enemy ship type that moves down the screen and attempts to shoot the player.

He is doing his best.

Let’s add a few more basic archetype enemies to the mix:

  1. A bomber ship that lays down mines
The Bomber!
  1. An aggressive ship that rapidly tries to ram the player, the harasser!
The Harasser!
  1. A “sniper” ship that sits in the back and tries to line up with the player to shoot them.
The Sniper!

The bomber is the closest one to our current enemy, so will start with him,

On my Enemy script, I created an integer array and named it EnemyID. This way, we can assign each of the 4 enemy types a number, and then only call the logic specific to their ID from the same script using switch statements.

Let’s look at each case of the switch statement that tracks each enemy’s movement pattern.

Nothing new here, just the base enemy moving down the screen.
Same logic for movement.

Now we get to the harasser, who rams into the player.

The Harasser has entirely different movement.

We set a local variable to track the player and the harasser’s own position. Using this, we can rapidly move towards the player with a Vector3.up, as we normalized the angle and now “up” means “the way this object (harasser) is currently facing”.

The last movement section is for the sniper ship.

The Sniper doesn’t want to get close!

The sniper moves into position on the y axis, then remains locked to that axis.

Great, so we have all of the movement for 4 similar enemies on a single script and we kept it organized!

Now let’s look at combat routines.

Base Enemy: Nothing new here. Move down the screen, shoot at will.
Bomber: Very similar, but we instantiate a new object (enemyBomb) and play a new sound effect.

Let’s take a look at the bomb the bomber lays down. The OnTriggerEnter logic is identical to the laser (it is destroyed on contact with a laser or the player).

When the bomb is placed down is it not active. Instead, a coroutine plays that “arms” the mine, turning on the collider. This also turns on a red light to inform the player of the now dangerous mine.

We call this in Void Start as the object is spawned in.
This contains the logic for the light, as well as the command for it to move down the screen.

Great, now onto the harasser…

The harasser has no combat logic. They ram the player. It’s all in their movement logic!

Placeholder pseudocode.

Finally, the sniper. We know that the sniper sits on a set Y axis value, but once they get there, their combat logic will kick in.

Most of this is the same as the base enemy.

Assuming the sniper can fire, we immediately call another method, EnemyStrafe.

This is similar to the harasser’s movement logic.

This function will line the sniper up with the player on the X axis. Once they are roughly lined up, the sniper will fire upon the player!

That’s it for this script, lets look in the Unity Inspector and change up some values!

The 4 enemy types are prefabbed.

NOTE: Any changes you make to variables in the Unity Inspector will supersede the code itself. This means we can make all of these ships have different fire rates and speeds in the inspector without messing with the code more!

We can swap the prefabs and set those variables here instead of in code!

In order to add them to the spawning system, I made an array of enemyType, then use a random range to select one and spawn it in. This is nearly identical to my powerup system array from one of my previous articles.

Line 9
The Array seen in the Inspector.

Let’s see them all in action!

Short display of all enemy types!

--

--

Jack Leavey
Jack Leavey

Written by Jack Leavey

I am a software engineer with years of experience branching into game development, specifically in Unity. Follow along for guides on creating game mechanics!

No responses yet