Road to Game Dev: The Final Boss. (Part 4: Boss Framework)

Rowan Mcmanus
4 min readOct 7, 2021

--

With our turrets having some basic functionality, it’s time to start telling the boss what to actually do with them.

Initializing the Boss

As soon as the boss spawns, we need to give it all the usual suspects; the spawn manager, the player, the UI manager, and so on. We also need to initialize movement with some of the same movement code we used on the smaller enemies, enabling the dramatic entrance you see above. There’s a few modifications to the movement code just to ensure that the boss can arrive at very specific locations. For the UI, we also need to know the total health of the boss; as soon as the boss spawns, we’ll have it check every turret it knows about and get a total of all their health. Each time a turret is damaged, we want it to send that damage signal back to the boss now and update the master total. Most of this is easy to handle; all it needs is a public function for damage and a for loop to grab health from each set of components.

Phase Changes

Now comes another decision point: How do we want to actually control the boss’s AI? We want the boss to always be aware of which phase it’s in, and grab data accordingly. We also need to know if we’re ready to change phases; we could technically do this by just tracking health thresholds, but that can be prone to some bugs where the phase may change before it’s ready to. Instead, each time a turret is destroyed, let’s run through and check all of them, and once they’re all gone for a phase, we can initialize the next phase.

Ending the phase itself also has a few tricks; this is where we destroy any projectiles still on the screen from the boss, and stop any turrets from turning if they’re still in motion. This is also where we check to see if the player has actually won by beating the final phase. To destroy projectiles, we’ll be using a new function: foreach(). The syntax on this can be a bit strange, but it allows us to do complicated for loops in a much more condensed form. Compare the foreach function for the projectiles to the regular for loops used below it:

Attack Pattern Framework

Now we’re just about ready to get into the real meat of the boss’s AI. Every single attack the boss makes need to be controlled somehow; some of these can be subroutines, while others are one-off functions. In both cases, we want to try and cut down on the number of functions we have to write as much as possible, so we’re going to aim to make our functions fully customizable. For example, we may want to have repeating waves of lasers, but we may also want to have a turret fire in a spiral. Both use the same type of motion, so why not create a function that can handle both with different parameters?

Before anything else, we need to have a way to actually call these attacks and store the information. Storing the information can be a challenge; when re-using functions like this, you still have to store the parameters somewhere. For now, I’ll be simply using arrays that store a different value for each attack depending on the phase; However, for further customizability you can use empty gameobjects with the data attached, or even .json files. These also have the benefit of de-cluttering the variables on the boss itself. In order to actually call the attacks, we’ll use a very simple “Commander” function:

Debug Menu

The bulk of the AI actually controlling these attacks will be stored on a separate script handling that logic. Before that, we have to create each of these attacks, and test them to make sure they work. This is where the concept of a “Debug Menu” becomes completely invaluable; you want to code in extra debug tools for yourself to allow you to control the boss and fire attacks at-will. The easiest way to do this is to create a bunch of booleans that you can only access via the editor, and then a function that checks them every update. Here’s an example of the attack controller:

With a debug menu ready to go and the boss’s basic movement and initialization ready, next time we’ll start delving into actually creating the attack patterns.

--

--