Creating A Homing Laser
Now that we just made a way for our powerups to come to the player on a key press, I’m going to move on to the task of creating a homing laser that goes directly to my closest enemy. This definitely took some trial and error and research to get it to work how I wanted it to, but in the end it was successful and I’m going to show you how I did it.
For my particular Homing Laser powerup and ability, I want to accomplish a few things.
- Find the closest enemy and move to that enemy
- If there are no enemies around, give the player a 5 second window before the powerup is deactivated
- Fire the homing laser on the press of the space key just like the normal lasers
- Give the player three homing laser shots per pickup activation
- Give a fire delay of 1.5 seconds between each homing shot so player is not overpowered
This initially may look like a lot, but it is all done between 3 scripts. The player script, the laser script, and our powerup script. Let’s get started.
In The Player Script
After creating the new prefab for the homing laser and attaching the laser script to it, as well as creating the pickup that will activate the ability and adding the powerup script to that, we will start the implementation inside the player script. First I’ll make a few new variables.
I’ve made a float for the firing rate specific to our homing lasers. An int variable to provide the number of shots allowed, which will start at 0. A bool to tell us if we have the homing laser. And a GameObject for the homing laser prefab that will be Instantiated.
First I made a new method that will set our bool for having the homing laser to true, and play the powerup audio as usual. This method will later be called on in our Powerup script. I then created a simple Coroutine that waits for 5 seconds before setting our bool back to false.
Next I added on to the ShootLaser() function of my player script. I added that if we hit the space key along with our bool for having the homing laser being true, our ammo count not equaling zero, and our stop shooting bool being false, then let’s now check some other things. If the enemy container where my enemies are tracked currently has enemy children and our homing shots is less than 3, as well as the time in our game is greater than our can fire float to say we can fire after our delayed fire rate, let’s start shooting our homing laser.
I created a new GameObject and call it homing laser and Instantiate the prefab I created earlier. I then communicate with the Laser script on the homing laser prefab and call for the method where the laser will identify itself as a homing laser which we’ll talk about in a minute. I also put in the same delay as before but with a different firing rate set to 1.5 so I can fire my homing laser every 1.5 seconds. I also tell it to take away from my ammo count, and add to the homing shots count. I then check if the homing shots is equal to 3, set our bool for having the homing laser back to false. I then check that if the enemy container has no enemy children, then start our coroutine we just made.
In The Laser Script
Next, we’ll move onto our Laser script. First we start with the variables. I made a float to calculate the closest distance to the enemies, a float that states the distance between ourself and the target, and a float to get the angle from the laser to the enemy just for personal preference. I also made a bool to tell the laser if it is a homing laser, as well as a Transform variable of our target enemy or the enemy the homing laser will go after.
Next I made the functions that will be used by the Laser script. The first function is going to find the closest enemy. The second will move the laser toward the closest enemy. The third will change our bool to true about telling the laser it is a homing laser.
The first function is going to use a foreach loop to find the closest enemy. Since our laser fires at the position of our player, this will still find the closest enemy to our player but I personally find it easier and neater placing it in here. In the foreach loop I tell the laser to run through each GameObject I named enemy in the GameObject array that we are given when we run the code to look for GameObjects with the tag “Enemy”. I then tell the float that represents our distance to the target that it should equal the distance between our laser position and the enemy position. If the distance to the target is less than our closest distance that is calculated each run through, then our closest distance now equals the distance to our target. It also then assigns our target enemy to equal the transform of the enemy from our array.
The second function tells our laser to move to the closest enemy. We do this similar to how we brough the pickups to our player on the key press. I’ll use Vector3.MoveTowards and pass through our current position, the position of our target enemy that we got from finding our closest enemy, our laser speed and of course multiply the speed by deltaTime. I’ll then make a new Vector3 variable to get the direction we need to go to get to the target enemy. This direction will be equal to our enemy position minus our position. I’ll also assign our float for our angle to the enemy using Vector3.Angle and inputting our direction vector and the transform.up function. The research showed this should’ve used transform.forward, but after some trial and error, the result I wanted ended up using transform.up instead. I’ll then use the transform.Rotate function to rotate the laser by our angle variable.
And finally, the third function that simply switches our bool to tell the laser it is a homing laser.
Then I update the Update() method of the Laser script and tell it that if it is a homing laser then use our FindClosestEnemy() method and use the MoveToClosestEnemy() method.
In The Powerup Script
Finally, we just need to make a few changes in our Powerup script that is attached to our homing laser pickup.
In here, I have updated the Update() method to state that if our powerup ID is not equal to 6, which is the powerup ID for our Homing Laser pickup, then allow the powerup pickup to MoveDown or MoveToPlayer on our C key press. I do not want this powerup to do this, as it is meant to be another rare powerup that functions and spawns the same as the Atom Bomb powerup I made. I then add a new case inside our switch statement of our OnTriggerEnter2D function that if the powerup ID is 6, then call for our FoundHomingLaser() method from the Player script, and go ahead and send a Debug message stating it was activated, then destroy the pickup as usual. The last thing to do is make sure to change the RarePowerups array of the Spawn Manager to include the Homing Laser Powerup. And now if my player picks up the Homing Laser pickup, we can fire homing lasers!