Feature: Homing Missiles

Kyle W. Powers
7 min readMay 5, 2021

--

This article will show how to create simple homing missiles for the Player to fire and a Power-Up they can collect to enable them.

The first thing to do is create a simple graphic to be used as the Homing Missile Prefab; it needs a Collider2D, a Rigidbody2D, and a new script component.

In the HomingMissile script, above the class, add a RequireComponent for the Rigidbody2D. We need to add some variables; the first is a Transform to hold the target the missile will seek out. Next are three floats, one for the missile movement speed, another for the rotation speed of the missile, and the last for the distance on the y-axis the missile can be at before being destroyed. The final variable that is needed is a reference for the Rigidbody2D on the Homing Missile Prefab.

In Start, get the Rigidbody2D component and assign _rigidbody to it. Now we have the reference to the Rigidbody2D that we will use to move the missile.

In Update, create an if statement that checks the missile’s y-axis position to see if it is greater than the _yDestroyDistance; if so, destroy the missile gameObject.

Create a FixedUpdate method. FixedUpdate is a frame-independent version of Update called every 0.02 seconds instead of every frame and is when Physics is handled in Unity. In FixedUpdate, create an if statement checking the _target is not null; this prevents an error if the target is null. Inside the if statement, add a local Vector2 for the direction to the target, which is the target’s position minus the missile’s position, but since the target’s position is a Vector3, we have to use (Vector2) in front of it to convert or cast it as a Vector2.

Next, to get the actual amount the missile needs to rotate, we have to Normalize the direction, which keeps the same direction as the vector it is used on, but its length is changed to 1. Create a local float for the rotate amount equal to the z-axis of the cross product of the normalized direction vector multiplied by the transform.up of the missile to create a perpendicular vector, which specifies the turn amount.

To make the missile rotate towards the target, we need to change the angularVelocity of the Rigidbody2D to _rotationSpeed multiplied by the rotateAmount. To get the missile to move towards the target, we must change the velocity of the Rigidbody2D to the transform.up multiplied by _movementSpeed.

Now, if you drag an Enemy GameObject into the Target field of the Homing Missile script, the missile will track and destroy it. The movement speed and rotation speed will need to be adjusted till you get the look you desire.

Back in the HomingMissile script, create a public method to assign the selected enemy to _target. Inside the method, we need three local variables; the first is a Transform that will be used to reference the chosen enemy to assign as the target. The second is a float that we will use to determine the closest enemy to the missile by distance. The last one is an array of GameObjects for references to the enemies active in the scene with the Tag of “Enemy”.

We now need to iterate through the array of enemies with a for loop to find the closest one. In the loop, we need an if statement to check if the enemy is null. If so, set the enemy to the transform of the current iteration of enemies. Now we need to set the value of distance using Vector3.Distance passing in the enemy’s position and the missile’s position to get the distance between them. Then use the continue keyword to tell the for loop to go to the next iteration.

After the if we need a local float for the next distance to check against distance, to get the value of nextDistance, we will use Vector3.Distance again but pass in the current iteration of enemies position and the missile’s position.

With the two floats set, we need an if statement to check if nextDistance is less than distance. If so, then set distance to nextDistance and enemy to the current iteration of enemies’ transform. After the for loop is completed, set _target to the enemy, which will be the closest.

In FixedUpdate, add an else statement to the if statement checking it _target is not null. Call AssignTarget to look for a new target and the missile to move forward at the _movementSpeed by changing the Rigidbody2D’s velocity.

In the Player script, we need to create a few variables. First is a GameObject for the reference to the Homing Missile Prefab that will be spawned. Next are two ints, one for the maximum number of missiles the Player can have, the other for the current amount of missiles the Player has. And finally, a bool to know if the Homing Missile Power Up is active.

In Update, add an if statement that checks for the Tab key to be pressed and _isHomingMissileActive to be true. Inside the if, create a local GameObject for the missile instantiated from the _homingMissilePrefab at the _spawnPoint position. Then get the HomingMissile script component from the missile and call the AssignTarget method on it. Subtract one from _currentMissiles, then create an If statement checking if _currentMissiles is less than 1. Inside the if, set _currentMissiles to 0 and set _isHomingMissileActive to false.

Create a public method to activate the use of Homing Missiles for the Player. Inside the method, set _isHomingMissilesActive to true and the _currentMissiles to _numberOfMissiles, so the Player can now fire four missiles when this method is called.

In the PowerUp script, add Missile to the Enum for the Power Up types.

Next, add a case for the Missile element in the Enum to the switch statement and call the ActivateHomingMissiles method on the Player.

Create a Prefab for the Missile Power Up, like in previous articles. Set it to Missile in the Enum.

When the Player collects the Missile Power Up, they can fire four Homing Missiles with the Tab key. The only thing missing is a visual missile count for the Player.

In the UIManager script, add a Text variable for the Missile Text. Then create a public method with arguments for the missiles remaining and the maximum missiles to update the missile text with the missiles remaining and the maximum missiles.

In the Player script’s Start, call the UpdateMissile method on _uIManager and pass in _currentMissiles and _numberOfMissiles to set the UI element to the starting 0/4.

In Update, inside the if looking for the Tab key input, call the UpdateMissile method on _uIManager and pass in _currentMissiles and _numberOfMissiles to update the UI element.

In the ActivateHomingMissiles method, call the UpdateMissile method on _uIManager and pass in _currentMissiles and _numberOfMissiles to update the UI element 4/4.

In Unity, create a new Text element for the Missile Visual and hook it up to the UIManager script.

With that now, the Player can see how many missiles they have.

--

--