Creating a Homing Missile Weapon

The next feature we will add to Galaxy Shooter is a homing missile weapon. This will give the player a satisfying new way to blow up the enemy spaceships. It’s one thing to just wish for some new feature, but another things entirely to make it. This is definitely the most complex feature yet!

Let’s break it down into all the parts we will need to create this:

  • Find a missile sprite online to use for this new projectile prefab
  • Implement a new input button that allows both keyboard and controller to fire missiles
  • Create a UI that shows how many missiles the player has available
  • Create a new powerup that gives the player missiles
  • Missiles will seek out nearby enemies (this is the tough one!)
  • Polish as necessary, adding sounds and additional visual effects

Thankfully, most of these parts are things that I’ve covered before in previous articles. I’ll cover the progress just a little bit, so we can get to the juicy part.

First, the missile projectile itself. Here’s a free missile that I found on https://opengameart.org/

I attached the player’s thruster effect as well.

To make this prefab, we’ll just copy most of what we did for the laser weapon. We can add a Collider2D, and a laser script so it moves forward automatically. Then we add the ability for the player to fire missiles.

Inside Player.Update

I’m using _missileOffset and _mirrorOffset in order to control where the missiles appear. I’d like for them to appear on the sides of the player, like they are coming out of missile bays.

New Player methods
Looks good so far.

Next is the UI. By limiting the amount of missiles and re-using the missile picture, we can use images to represent how many missiles remain.

Always re-use assets when it’s convenient!
Add this to Player.FireMissile
New method in UIManager

Whenever the player’s missile count changes, we can tell the UI manager to activate or deactivate the right number of missile images.

When the player runs out of missiles, they can no longer use them.

This time for the new powerup, I decided to go with a different design that uses the missile sprite yet again, instead of having text.

Edit the enum in the Powerup script.
In Powerup.GrantPowerup
New public method for Player

Implementing it is just as easy as all the other powerups. Just add it to the enum and have it call another Player method.

Now for the hard part. We’ll want a new Missile script that will cause the missiles to seek enemies by rotating and moving toward them. This can take a lot of trial and error to set up, since dealing with rotation is tricky in any game engine, and Unity is no exception.

The main idea here is to acquire an enemy target, get the direction toward that enemy as a vector, and then use that vector to determine how the missile should rotate. By using Vector3.SignedAngle to compare the missile’s local direction to the target direction, we get some number of degrees that we want to rotate. We can then limit it by _turnDegreesPerSecond so we don’t have missiles that immediately snap towards the enemy target.

Missile.Update method.

Now, how does a missile acquire targets? We can do so by getting a list of enemies, then going through all of them one at a time with a foreach loop. Inside the loop, it will compare each enemy to the closest one we have yet found. If the current enemy is even closer, it will pick that one. This will guarantee that missiles will track the closest enemies whenever they need a new target.

Missile.SeekNewTarget, a helper method that gets a new target transform.

Now we can attach the script to the missile prefab, assign _velocity and _turnDegreesPerSecond to some reasonable values in the inspector, and then run the game to try it.

Looks pretty good, but there’s some minor problems. Both missiles tend to go after the same enemy, and when the enemy is destroyed by one missile, the other loops around the enemy explosion in an attempt to hit it.

We can at least fix the looping problem easily by giving a new variable to enemies called “_isDead”, which missiles can then use to determine that the enemy is exploding and shouldn’t be targeted.

A new property in Enemy script
Enemy.EnemyDeath

We can use a Property to help. _isDead information is accessible by the Missile and other classes, but by including “private set”, we ensure that the Enemy is the only thing that determines if it’s dead.

A change to Missile.SeekNewTarget
A change to Missile.Update

Now we can use this new property to make the missiles a bit smarter. When seeking a new target, the missiles will ignore enemies that have _isDead set to true. The missiles will also save the enemy script and check if it’s dead on every update, so they know to look for a target that isn’t exploding.

Awesome! Now we have a new toy that makes blowing up enemy ships easy. There’s still a lot of polish we can do for this missile, like adding sounds, but getting the basic feature working perfectly well is a great accomplishment.

--

--

--

I’m a passionate and talented software engineer seeking an opportunity in game development.

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Tutorial: Using GitHub Through Terminal

Load balance your node app with Docker + NGinx

What are Microservices? and Why do we use it?

How do AWS Certified Professionals Help Organizations?

Push Spark DataFrames to ElasticSearch index

How to save some $$$ using Amazon Web Services?

The Backbone of a Website: Weeks 1 and 2 of Building and Uploading My Website

Best Practices for Writing Documentation

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Blake Zoeckler

Blake Zoeckler

I’m a passionate and talented software engineer seeking an opportunity in game development.

More from Medium

Doxing Examples

Art for Healing

№1

Split it up — Part 1