Creating Modular Powerup Systems

One of the key things for creating a more modular system is the idea of giving an instance of your class (an object) different behaviours depending on the context and/or the settings you decide on. For instance, let’s say we have an ‘Enemy’ script but want to specify and call different behaviours depending on whether it’s a red enemy, a blue enemy, or a green enemy. We could create scripts for each of these, and there might be times when this’d be a better course of action (particularly if the code for each of these enemies is actually sufficiently different and complex), but in this case it’d probably be easier and more organised to just accommodate different behaviours within the same class.

While a switch statement or if statement should allow us to specify these different behaviours/blocks of code to run for each of the enemy types, we do still need a way of telling this instance of the script what that enemy type is. To do this, we might choose to use some form of integer identifier or a string identifier:

These would each have some advantages and disadvantages: using a string lets us use a more meaningful name (making the code a bit more readable), while using an integer has a less meaningful name (and most likely needs a comment to clarify which numbers refer to which enemy type) but reduces the risk of inputting an incorrect value just by a misspelling. Someone on the team might accidentally write ‘Gren’ or even ‘blue’ (missing the capitalisation) and instead the Default case will run within the switch statement. There can be some workarounds, such as calling the ‘toLower’ method on the string received (just to standardise it to lower case), but this doesn’t get round the essential problem here.

I’ll cover this more in a separate article, but what I’d recommend in this case is using an enum or ‘enumerated type’. Like structs, enums are one of what’s known as a user-defined data type, and specifically they allow us to provide meaningful names for a set of integral constants. For us, this means we can actually see ‘Blue’, ‘Red’, and ‘Green’ as options in the inspector if we choose, select them, and not need to worry about typing them out or spelling them correctly. Their actual values will be integers just like the integer ID system above (so Blue will actually be 0, Red will be 1, and Green will be 2, so long as we order them that way in the enum declaration or specify these values):

This should give us the best of both worlds when it comes to calling different methods and behaviours from instances of the same class: meaningful names with the consistency of integers.

As a side note, I’m currently using this sort of logic for the powerups in the 2D space shooter, but we could use this kind of more modular system for different enemy types, character types, collectibles, etc. It’s incredibly time consuming and, personally, easier to manage (as I’m not having to rewrite code that’s consistent between different types), so I’d highly recommend giving it a go sometime 😉

Game Developer | Game Design and Literature Graduate