Giving the enemies some teeth
Up until now, our enemies have just been moving obstacles to avoid for the player.
We’re going to give them the ability to fight!
We’ll need a new version of the laser game object prefab.
Let’s duplicate our current laser prefab, break the prefab connection, and rename it EnemyLaser.
We’ll then need to create a new tag, “EnemyLaser” and set that on our new EnemyLaser prefab.
Modifying our Laser script
We are going to be able to reuse our current laser script for the new EnemyLaser game object.
We just need to make a slight adjustment.
Up until now we have only had to worry about what happens when the laser game object is above the player screen, but now that enemies will be firing them we need to know if they go below the player screen.
So we’ll add an or statement to our if statement and use the value that represents our lower player screen bounds, in my case -5.5.
Modifying our Player script
On our player script we add the OnTriggerEnter2D() method and check for collisions with objects tagged “EnemyLaser”.
Now we’ll know when the player has been hit by an enemy laser and trigger our LoseLife() method.
Modifying our Enemy script
We’ll start by adding some variables to our Enemy script as shown above.
I will implement 2 firing enemy types and 1 that doesn’t fire.
Next, let’s assign the appropriate prefabs for our new variables to the Enemy script component before we forget.
We’ll update our null checks for the new variables.
In our Start() method we generate a random assignment for our Firing type just like we did with our move type.
We’ll need to add a method for the enemy to actually fire the laser, based loosely on the code we’ve already used in our player script.
We need to change some default settings on our EnemyLaser prefab in the Unity editor.
In my case, positioning the Direction as 0,-1.9,0 was ideal.
I’ve modified the variables in the Laser script to no longer hard code set the values so we are relying on what is in the unity editor.
Back to the Enemy script
In our Enemy script, Update() method we add a new switch statement for _enemyFiringType.
For case 0, nothing is meant to happen.
For case 1, we fire a laser similar to the player laser.
For case 2, I plan to add in a beam firing mode, but we’ll get to that in a bit.
At this point, we should be able to run the game and have working enemies firing when they are randomly assigned to and the remaining enemies just not firing as usual.
Adding the beam laser
I’ll reuse our laser game object, scale up to be taller than the screen so it appears to be infinite length to the player, change the color, and rename it.
We’ll set the tag to EnemyLaser, Sorting Layer to Foreground, add a collider with Is Trigger enabled, and a rigidbody with gravity scale set to 0.
Adjust the collider as needed to match the image on screen.
If you’ve already created a prefab, make sure to apply your overrides.
Otherwise, create a prefab.
Modifying our Enemy script
Back in the Enemy script, we’ll add a variable for our new prefab and a temp variable to hold the beam GO that is instantiated and parent it to the enemy game object.
We’ll drag our LaserBeam prefab onto our Enemy script component.
We’ll add the FireBeam method as shown above.
We need to have a tempGO to store the instantiated game object so that we can parent it to the enemy ship and move with that ship.
I’ve also update our FireLaser() method to have temp game object (don’t forget to add to the variables at top of script) so that I can adjust the laser speed.
Modifying the Laser script
To do that, we have to modify the Laser script by adding the SetSpeed() method to it.
Back in our Enemy script, we add the case 2 code of our _enemyFiringType switch statement to call the FireBeam() method.
Now, what have should be working at this point.
The only thing is that we have equal chance to get the beam laser as the regular laser and non-firing enemy types.
I want to weight the beam laser to be rarer than the other two or the game can be really difficult before we’ve even gotten into the later waves.
I also don’t want the beam to exist on the enemy for as long as the enemy lives.
To accomplish that, we start by adding a coroutine, BeamLaserCooldown with a float variable for the delay time.
After the delay, we destroy the _TempEnemyLaserBeamGO.
When our FireBeam() method is called we start the newly created coroutine.
Reducing the chances of an enemy being LaserBeam type
We’ll need to modify our Start() method a bit.
If we hover over the “Range” call on Random.Range for _enemyFiringType, we can see that the first number is inclusive (will be included) and the second number is exclusive (will be excluded).
So with a new value of 0,2 we can only ever get 0 or 1 results which means none will be assigned BeamLaser type here.
We’ll generate a random number between 0 and 9 (10 digits) and check for it lands on a particular number, I’ve chosen 7.
That gives it a 1 in 10, or 10% chance of firing off our if statement and reassigning the _enemyFiringType to 2.
After playing around with it a while, I changed the odds a bit.
I’ve made it more likely to land on the random number but I’ve excluded any enemy whose move type is 0, since that is the straight down move type.
Straight down with an infinite laser is hard to shoot down!
I’m pretty happy with the results I’m getting now, so I’ll leave it here.
All done, run it and get to dodging!