Unity Dev: Homing Missiles
We can’t just rely on our ship’s laser to get the job done. This is a hostile alien fleet after all. A never-ending hostile alien fleet. Some jobs require a more… heavy handed approach.
There’s a couple things I want out of a good alternative firing method.
- Area damage, otherwise known as an AOE (area of effect). When my missile explodes, it should potentially take out multiple enemies at once.
- Some degree of intelligence. My missiles should track down enemies and move towards them by course correcting.
- Should be a time bomb. Since all the enemies are moving around pretty quickly and then warping back to the other side of the screen, I don’t want my missile flying around the screen like a chicken with its head cut off.
- It should look like a, y’know, missile.
- Should have an ammo system and be usable with a right mouse button click or the north button on a gamepad.
I can really only pretend to dabble at pixel art (or any art in general), so I used the wonderous reaches of the internet to find some asset packs I could use in my game. itch.io is a truly spectacular resource for these types of things and can really put a nice shine on your game. Which, of course, got me pretty excited so I swapped out a number of the existing assets in my game with some retro pixel goodness (my favourite kind of goodness). You can find the asset packs I’m using at the following links:
Basics first. We create a new GameObject using our missile sprite, give it a 2D collider (set to Is Trigger) and a rigidbody (remembering to turn gravity off for it). I’ve started using the Polygon Collider 2D for this project as it allows for more accurate colliders based on the shapes of my sprites.
Make a new C# script for the missiles and attach it, then turn the GameObject into a prefab. For now, we can set it up to just move the missiles to the right as soon as they’re spawned.
Next up, we need some user input to spawn a missile instance. I’ve created a new Action in my Player Action Map for just this purpose.
Hook up your new OnFireMissile event in your Player Input component, and add create the code that’ll Instantiate your missile into the scene. There’s a bit extra in this screen that assumes a basic ammo counter for the missiles and a relevant display in our UI Manager.
This part has a couple different aspects to it, but is also the most rewarding!
First, to get the missile to attempt to follow a specific enemy, we need to tell it enemy it should be following. We’ll do that by collecting a List of all the enemies that are active at the moment the missile is fired. From there, we’ll take the list of enemies and iterate through each of them. As the script calculates the distance of each enemy (relative to where your ship was when you fired the missile), it will compare the value against what is currently set as the
closestDistanceSqr . If that enemy has a smaller distance than what is currently stored in that value, it becomes the new
closestDistanceSqr and its transform will be stored for use once this loop is done.
Upon hitting the last enemy in the list, we now have our
bestTarget which is the transform of the enemy that was closest to us when we fired out missile. Seems like a long time ago, yeah? Don’t worry, it all happens insanely quickly.
Now our Player has information about where the nearest enemy is to it, but we need our HomingMissile to have that information so it knows where the go.
Pretty, simple, we just create a variable inside of our
OnFireMissile() method which gets the value generated from our
GetClosestEnemy() method as a Transform. We then fetch our
HomingMissile component and call a script called
MissileTarget() where we simply load up a variable in our HomingMissile script with the important information.
Now we’ll expand on our Missile’s current movement, which is just driving it straight forward (to the right). The general idea is that we’re going to find the Cross product between the direction our target is in and the direction that the rocket is facing. When we first Instantiate it, it’s going to be facing and moving
For a much better explanation than I could ever hope to provide about the math going on here, I recommend checking out How to make a Homing Missile in Unity on the Brackeys YouTube channel which, you’ll see, had a heavy hand in my solution here. As long as the HomingMissile object has a target to seek out, it will rotate itself as it moves through space, creating for some interesting paths. If it has no target, or loses its target, it will just carry on straight in the direction it was already headed.
What good is a rocket if all its doing is aimlessly following an enemy around?
We’ll set up an IEnumerator in order to create a countdown for the value of a
This will Instantiate an object which contains an animation of an explosion and is set to be quite a bit larger than the actual Missile sprite. In addition, we have a collider that encompasses the explosion animation, making for a large exploding area that will nuke any enemies that happen to be in the area. Silly enemies.
Use the IEnumerator in a
StartCoroutine() in the HomingMissile’s
Start void to begin the countdown to ultimate destruction.