Part 1 — Fire & Forget: Creating a Smart Homing Missile for your Unity Game Project!
Objective: Implement a new weapon to your player’s arsenal in your Unity 2D Game Project. Make it smart. It should be able to detect, track and destroy any enemy game objects present in the game scene.
Part 1 — Creating the 2D Sprite and setting up the logic in the PlayerScript and the Enemy scripts.
Thus far, our little spaceship can only defend itself with its dual laser canons. Sure, he sometimes collects a power-up giving him a temporary ability to fire a triple-shot laser spread in an arc. Now, let’s beef things up a bit and give him a smarter weapon: a homing missile to seek out those bad alien vessels!
I should have started with a simple prototype game object, but I’m really a visual type of guy, so I spent some time looking for a suitable “missile” asset. I finally found what I liked in PNGHUT.COM, a Rocket Propelled Grenade (RPG) launcher with an associated RPG rocket png.
I extracted the RPG png, turned it into a 2D Sprite, and created a Prefab with the following parameters (see below). Note the Tag is cut off in the image and should read “PlayerHomingMissile”. I added a 2D Rigidbody, and adjusted the 2D Capsule Collider to capture the “warhead” portion of the “missile”.
I then duplicated the Player’s thrusters, adjusted the scale and color palette, and set it as a child of the Player’s Homing Missile.
Now that your missile Prefab is complete, let’s jump into the basic setup in the Player and Enemy scripts…
I began by adding the following four private variables: a Game Object _playerHomingMissilePrefab holds the missile Prefab. The bool _isPlayerHomingMissilesActivate lets us know if the Player is currently armed with homing missiles (this will be flipped to True when the Player collects the homing missile power-up or when the logic determines there are missiles remaining). Integers _homingMissileCount keeps track of the remaining missiles (think ammo count) and _maxMissileStores limits the amount of missiles our player can carry.
Drag the PlayerHomingMissile prefab into the appropriate field in the Inspector while looking at the Player game object.
I then added in the Update() method a couple of IF statements. The first determines when the “M” key to be pressed (“M” for Missiles). When this happens, the logic looks to see if the Player has collected or is currently armed with missiles. Only then will the Player be allowed to fire a missile by calling the FireHomingMissile() method. The second IF statement simply checks to see if the “missile count” is depleted, and if so, flips the bool back to False.
FireHomingMissile() is the method used to instantiate the Homing Missile Prefab at the player’s position, with a slight offset for visual aesthetics. We reduce our Homing Missile inventory by reducing _homingMissileCount by 1 and finally update the UI Text to reflect that new value.
We also need to ensure collisions between the Homing Missile and the Enemy ships are detected. This is done by adding the Tag “PlayerHomingMissiles” to the OnTriggerEnter2D() method of the Enemy script.
Remember that we set up two private int variables in the Player class to track the maximum quantity of missiles the player could carry and the remaining missile stores. I set up the maximum via a variable instead of hard-coding a value to allow future expansion. In my version of the 2D Space Shooter project from Game Dev HQ, I opted to set the max missiles of my Player to “25”, and I generously started off my player with 20 of these lethal weapons in its stores.
Moving briefly onto the UI Manager, we need to set up our UI elements so the Player can visualize in the UI the quantity of Homing Missiles held. In my UIManager class, I declared a private int to store the max missile value from the Player class.
From the Hierarchy, select the Canvas, add a UI TMP Text field and rename it: “Homing_Missile_Count_text”.
In the Inspector, drag it into the Homing Missile Count text field.
I then communicated to the UI Manager from the Player script and called the two functions in my UI Manager by caching these int values and updating the UI display at Start().
Every time the Player collects missiles via a power-up, the value of that power-up (homingMissilesCollected) is added to the _homingMissileCount, and then we call the UpdatePlayerMissilesStores() method.
UpdatePlayerMissilesStores() checks to see if the _homingMissileCount value is less than 0 and if so caps it at 0 so the Player doesn’t end up with a negative value for missiles. Similarly, if the Player collects enough missiles to fill his missile stores (set by _maxMissilesStores), then the upper value of _homingMissilesCount is also capped at that value.
Once we’ve established that the Player’s missile stores are within the legal bounds set by the developer, we then call the SetMaxMissileCount() and UpdateHomingMissileCount() methods in the UI Manager to update the UI display.
SetMaxMissileCount() caches a reference to the Player script _maxMissileStores into maxMissiles then stores it into _maxMissileStoresUI.
UpdateHomingMissileCount() does the same with _homingMissileCount into homingMissileCount. We then use this data to update the UI text field.
The entire UpdateHomingMissileCount() method, which also varies the text color based on remaining missiles, is shown below:
You set the color code system for missiles remaining to multiply the _maxMissileStoresUI variable by a percentage. This will make the UI adapt to whatever the max missiles are in case the value were to change during gameplay (i.e.: ship upgrade).
This about does it for Part 1. Meet me in Part 2 where I will take you through the steps to create the Homing Missiles collectible Power-Up. We will make some slight adjustments to our SpawnManager and PowerUps scrips as well.
Here’s a teaser 😋 …
Thanks for reading :)