This was quite the challenge, there are actually quite a few ways of doing a homing missile in Unity, and many of them require some advanced mathematical knowledge that I’m ashamed to admit I’m not up on. And even though I may have depended a little too much on research *cough*, even the rest of the implementation of getting it to work with the rest of the program was an adventure! Anyway, let’s get right to it!
Once again, I modified the current powerup to a new color and added similar pixelized text to it to stay ‘on model’ with the rest of the game.
Once installing the script, I gave it an ID of 5 and dragged it into a new 6th slot in the spawner!
While I was implementing the actual Homing missile behavior, I used a free graphic I downloaded off google.
Admittedly it doesn’t fit at all with the rest of the game but it did the job in the meantime until I was able to kitbash together a more proper looking missile from the enemy and player graphics:
While it’s a little fuzzy here, it’s only going to be a very small asset on the screen and it has the semblance of original detail so it looks great moving around while it’s on the prowl for enemy ships!
So to begin with, I added the missile on screen and created a script for it called HomingMissile.
Homing Missile code:
Pretty straightforward: I need a target for the missile to follow, the target will be anything with the ‘Enemy’ tag that will be initialized later, a handle for the rigidbody, and we’ll need a thrust speed and rotation speed for the rigidbody.
The missile will explode at one point, so we’ll put a modified explosion prefab in it. I gave it _missileGoBoom because that's what missiles do! Finally, we have a variable which will eventually limit our missiles life to 5 seconds, after it go BOOM!
In the Start() function, we’ll actually assign the rigidbody component to the variable handle, and here using the FindWithTag function, we’ll look for anything on the screen that has an Enemy tag. Finally, a couple of Coroutines for the missile to self destruct and find new targets are called.
Here’s the Coroutines: Self destruct will wait for _lifeOfMissile, which is 5 seconds, say stop looking for a target and destroy yourself with the DestroyThisMissile function.
The DestroyThisMissile instantiates the small explosion and then finally destroys the homing missile GameObject.
I’m not sure if a 20th of a second is too fast for the missile to start scanning the game screen for a new enemy, but it seems to work. We tell it what to do in the meantime in Update().
This is the heart of the homing missile script. if there’s currently a target, we create a variable called dir, which gives us the difference between the target and the missile's position and normalizes it. My understanding of why we need to do this step is it gets rid of the magnitude (or the length of how much an object is traveling) and reduces it to 1 unit. Basically, this gives us a direction and gets rid of some extra numbers reducing the need for Unity to do the math and that’s always good.
Then a new variable called angle is created and uses a mathematical formula to give us the angle from the positions of y and x and it gives us the angle in radians. GameDevHQ has a detailed explanation here. I know I myself will be closely studying it soon!
a new angle rotateToTarget is made which will ultimately change the rotation of the transform to the newly calculated angle variable but holds it in a variable to be used with the Quaternion.Slerp function that helps change the rotation over time.
Admittedly I don’t understand all of this myself, hence me going to the GameDevHQ link later to study up on much-needed game-related math.
When a game object enters the missiles box collider, it will check to see if it’s the player or an enemy ship, if it’s a player, nothing will happen, but if it’s the enemy ship, it will call the enemy ships destruction function and then destroy itself.
So let’s put a missile and an enemy ship and see how it works.
WooHoo! We’ve got homing missiles!
Now all we need to do is get the powerup to communicate with the player, have the player shoot the missiles, and also communicate to the UI to update how many missiles are left when we’re shooting them:
First of all, the powerup code:
We’re really beginning to see the advantages of the switch/case function here. Can you imagine the mess if we were using if/then statements?
Ok, let’s head on over to the player script and write the activate missiles function:
Before we do anything, let’s initialize some variables:
First we create a variable for the weapon type. Then a holder for the missile, and finally how many missiles.
Just like the powerups, we’re going to code our weapons with ids. 0 will be lasers, 1 will be missiles. So when missiles are activated, we’re going to change the weapon number and give the player 5 new missiles to play with. the UI manager is kind of out of the loop so we need to tell it every time we change the players missile or ammo stats. It’s better to be redundant than sorry!
Checking the fire button:
Instead of immediately firing a laser when we hit the spacebar now, we’re going to need to know what it is we’re firing. Unlike the triple laser, we’re going to give the missiles its own firing function and we’ll choose it by the _weapon variable and the switch. if it’s 0, go ahead and fire the laser, if it’s 1, Fire the missile.
Here, we check to see if the player has more than 0 missiles, if he does, he can fire away! We’ll reduce the missile count by one and immediately update the UIManager with its own UpdateMissileCount function. we’re going to be using the same _canFire logic to keep the player from spamming the spacebar and shooting all 5 missiles at once. Like the laser, we create an offset and instantiate the missile a little above the player.
If the player runs out of missiles to shoot, it defaults to the else statement where the UIManager is updated again so it reflects the current state of no missiles and resets the _weapon back to lasers so the player can keep shooting his normal ammo.
Just like the Ammo UI, I created an image for the missile icon and a Text object called Missile_Text to access with the UI manager. Since we went over this before, we’ll just concentrate on the code:
We’ll create a reference to the text object so we can update it, and a _missileCount variable which, like the _ammoCount, will reference the players missileCount variable and make a copy for its own use.
And to round off the code, we make a copy of the players missileCount variable, and use that to put the text on the screen. I guess we can do it directly, but I think it would be less readable if it said:
And there we have it! It was quite a run around the entire code environment, but I think it’s quite a bit of growth from moving a cube around with transform.Translate, don’t you think? :D