Galaxy Shooter 2D — Heat Seeking Lasers

The enemies won’t even know what hit them!

Pablo Gómez Platón
Nerd For Tech
4 min readMay 28, 2021

--

My ship weapon arsenal has been getting a little stale, with just two weapons (if you include the default one). I’ve decided to add Heat Seeking Lasers, only looking for ship targets (the asteroids are ignored, but that doesn’t mean that they can get in the way).

It’s a basic weapon, but one that requires a bit of work to implement and to optimize. That’s why this article is completely focused on explaining how I implemented this.

Preparations

  • I implemented the weapon swap in the Ship script, where it will replace temporarily the default laser prefab for the Heat Seek one.
I use coroutines to handle the duration of each powerup
  • I created a “new” laser prefab where the Heat Seek Laser script will be added.

Implementation

Remember, before implementing a feature, you should always design it first. You can design it along the way, but it will take you more time to code as you‘ll think about what the feature should do and how to code it at the same time.

The Heat Seeking Lasers should behave like this:

  • The laser needs a method to detect Enemies that surrounds the Laser. Optimally, using a Coroutine to avoid checking every frame for enemies and using Physics2D.OverlapCircleNonAlloc to detect enemies will allow for fast and optimized collision queries.
    The Coroutine will be started in the OnEnable() method and will always be active until the laser is destroyed or disabled.
Click to Zoom. These variables are necessary for the Lasers to work.
  • The laser will chase only one target that has a Enemy script, and is the closest one to the laser in distance (the asteroid is dismissed). That means that, for every enemy detected, the laser will have to check who is the closest one.
To get the nearest contact, the laser must loop through the enemies detected in the OverlapCircle. This is a somewhat expensive operation, so, to counter that, that’s why I chose to use Coroutines, to avoid checking for colliders / targets every frame.
  • If a target has been selected, the GameObject will be rotated towards the direction between the laser and the chosen target. In any case, the laser will always move upwards in its local axis and with a constant speed.
  • A target is deselected when the chosen Enemy has no life left, or a reference to that Enemy has been lost. The laser will lock on to that Enemy until the enemy is destroyed, and we also skip the expensive operation of looking for enemies.
  • When the laser makes contact with a Damageable entity, deal damage to that entity and self-destroy (or self-disable).
  • If the laser exits the screen in the Horizontal Axis, the laser will wrap around and enter again from the opposite side where it left the screen. Also, if it exits in the Vertical one, it will self-destroy / self-disable.
  • As an extra, I want to visualize the radius of that laser for balance / debug purposes. To do that, I use Gizmos.

End Result

Sometimes, a basic feature has its own complexity. Just remember that when you estimate how much time will it take you to code one.

--

--