Best way to create an upgrade system that is easy to expand?

Hello,
I like games with upgrades, lots of different upgrades to be precise. But I haven’t found a good implementation yet that I like.

I would like it to be modular and easy to upgrade. So something to hardcode with if statements is out. I would have to add new if statements for each upgrade.
I would like each upgrade to be its own resource or scene. So that the upgrade code only has to be managed there.
But I just can’t find a good solution to the problem.

Let’s say I have a building in the game that produces 1 thing per second. There is a function that increases the thing by one every second.
I could say the building checks all unlocked updates before each production and adds the production multipliers. Would work.
But what if I want to add an upgrade that produces 2 extra things with every production? Now I would have to adapt the code of the building so that it recognizes the new upgrade type.

I think it would be best if the building would call the upgrade’s function instead of its own. But what if I have multiple upgrades for the same thing. What if there are many buildings and countless upgrades, at some point there will be performance problems.

So I’m not looking for a solution to a specific problem, the building is just a possible example. I am looking for a good approach to build an upgrade system that is easy to maintain and expand. So I don’t need code for it, the concept is what I’m looking for.

Hmm…

Producing a generic system that facilitate upgrades requires you to define what is upgradable. In other words, what parts of the system should be able to change? Once you have this information, you can then start to categorize the upgrades and build a system that supports these upgrades. Some upgrades may modify data (as in your building example), and some will change the fundamental behaviour of an existing action.

High-level upgrade framework

As mentioned, different upgrades will impact the system in their own way. Modifying the production rate of a factory requires a simple modification of the underlying data, namely the “production rate” variable. We may describe such an upgrade as being data-driven.

On the other hand, an upgrade that switches a car’s wheels for propulsion jets (in order to fly) is not something easily achievable with a data-driven system. I personally view such an upgrade as a different module - it’s a different thing.

Supporting data-driven upgrades

To support data-driven upgrades, it would be beneficial to define a single data structure that contains the data needed for an upgradable object: a generic interface through which the object and its upgrades communicate. The object’s behaviour should mostly rely on this set of data.

(Example) Factory Data:

  • Production rate
  • Fuel consumption
  • Building requirements

The object can then contain a list of upgrades that modify the dataset thus modifying the object’s behaviour.

I know you are not seeking code but it helps to further illustrate the concept

class_name Data

var production_rate := 2.0
var fuel_consumption := 2.0
class_name Upgrade

func ModifyData(Data: data) -> Data:
    # Modify the data here
    # Return the modified data

I’m not really a GDScript-user so take the code in the snippets with a good amount of salt.

Supporting modules

Modules are different. Essentially, modules and nodes are pretty interchangeable terms which is beneficial in the context of Godot.

To support modules you should make your upgradable object capable of adding and removing nodes from itself. These nodes (modules) would then perform their own behaviour. Using the previous example of transforming a normal car into a flying one, the car may have pre-defined locations on its chassis where modules can be placed: wheels, jets, tank treads, or something else.

The concept is similar to how hardware modules communicate with one another; through ports, cables, wirelessly, and so on. Actually, I find hardware to be a great analogy for OOP architecture in general. I mean, how would you upgrade your PC setup; how is a VR headset different from a 1080p screen in the context of your setup?


Hopefully I’m getting the concept(s) across.

2 Likes

Something modular depends entirely on the design.

You could take rpgs as inspiration and build something like an equipment system. Where the building has innate stats and you equip the bonus to them. You could even add an upgrade system where buildings start with a few slots and then you purchase additional slots to equip more upgrades.

Then add and multiply all the bonuses to the final result.

This video explains the strategy pattern. Sounds easy to use and expand.

Thank you for the detailed explanations. I first have to think about it a bit until it clicks, but I think that will help me a lot.