GameDevHQ — Day 13 — Building a Better Homing Laser Pt. 1

Aloha!

After finishing the rest of the features required for the Framework phase there has been one lingering challenge left that I needed to complete and that was debugging the behavior of the homing laser power. To recap the development of this feature the goal is to create a firing mode that will discover the closest enemy to the player and then redirect any fired shots directly into any valid targets. If there are no targets that exist in the scene then the shots will travel directly forward until they either despawn from hitting the boundaries of the screen or a new target spawns. Once a new target spawns the shot should then redirect itself into the target. With the current version of the feature I have been able to program the shots to successfully find a target and travel to them. Additionally the shots will travel in a straight line if there are no valid targets for them to travel to. The issue that is occurring is that in a situation where there are multiple targets on screen at once, shots fired in rapid succession will travel to the first viable target and then ignore the rest for a short period of time after which every shot will select the same next viable target at the same time and then shoot towards it.

My attempts at fixing this problem has gone through three iterations at this point with the fourth being my goal for tomorrow. The general mechanics for redirecting a shot into a selected target has been more or less the same for each iteration however the process for selecting a target has been the primary change each time. The primary challenge has been to find a fast and efficient way to identify all possible targets in the scene and select the best one, with the list of possible targets updating each time a new enemy is spawned.

The first iteration of this feature attempted to identify its target by extracting a list that is created and populated by the Spawn Manager in the scene. The list contains a reference to every enemy game object that is created and when it is extracted by the HomingLaser script it turns the list into an array to parse through its contents using a foreach() statement. It will then compare the distances between each enemy game object and the player character and choose the closest one as the ideal target. This method resulted in proper tracking but failed to update its targets quickly and relied on the list of values that were being updated periodically rather than updating its list of targets on the fly. This also included some extra overhead where the list that would be extracted would contain an entry for every single enemy that was ever made and parsing through the array would mean identifying and skipping over entries that contain game objects that have already been destroyed.

To attempt to remove the reliance on the target collection being generated by another script and isolate this process into the HomingLaser script I removed the array that collects entries whenever an enemy is created. The alternative was to remove the call to extract a list and instead create an array by finding all objects in the scene with the tag “Enemy”. This provided a method of target acquisition that updated more often but was a very expensive process to be running constantly. Additionally the result still yielded the undesired behavior where shots would not recognize alternative targets once their previous target was destroyed. In attempt to find a solution to this issue I consulted other participants in the program, Austin Mackrell and Dan Schatzeder for some assistance. This led to the third and current iteration.

The main changes that were implemented for the third version was to replace the method of finding all objects with a certain tag with a reference that checks for all children of the Enemy Container object. This meant less searching and a more direct and constantly updating reference for our list of potential targets. Another additional change that was made was to how the script detected if an enemy was destroyed. The initial method would check for the collider of the object and if the collider did not exist it would count the target as destroyed and attempt to find a new target. After consulting with Austin we decided to change this to a boolean switch that would activate to true upon an enemy being destroyed. This all worked as solid optimization changes but we were not able to nail down a proper solution that solved the issue where the lasers were still slow to update their targeting. One hypothesis we have for this is that the calculations to determine a new target take too long to perform the more targets there are which hampers the performance of the shots to quickly select a target before they fly off the screen and despawn. This is the current state of the function and my plan for tomorrow is to attempt a fourth version that moves the closest target calculation out of each individual shot and into a global handler that constantly keeps track of what enemy is closest to the player and the shots will simply reference this output when for their target acquisition instead of determining it themselves. I will report back about the progress of this approach tomorrow in part 2. Mahalo for reading.

— Kurt

An aspiring game-dev from Hawai’i. Previous experience was in programming and animation work.