GMS 2 [SOLVED] Better to keep upgrade logic in a single object or use instance_change() ?

Papa Doge

I'm planning out the logic for an RTS that has buildable/upgradable structures. For example, the player might build a sentry that has turret guns at first but then can pay an upgrade cost to add or maybe replace with a flamethrower.

In planning this out I'm considering two paths...

A) The sentry object has a variable called "has_flamethrower" that is set too true if the player has paid the upgrade cost. Then in the step event, I would have a block of code that says "if (has_flamethrower == true)" and if it is, change the sprite index, change the structure portrait (displayed in the HUD when selected), and finally run some code that makes the turret spew flames when enemies are within range.

B) The sentry object is first placed as a standard sentry with default sprites and functionality. When the player pays the upgrade price, I could swap this standard sentry with an enhanced sentry that has the flamethrower capabilities, flamethrower sprite, and flamethrower HUD portrait.

I estimate to have in the ballpark minimum of 13 different structures that will use this system for upgrades, so it needs to be somewhat scalable.


Of the two options above, does one stand out as clearly the better way to go? Are there other options I should be considering here like a parent child relationship of some kind?


this is kind of a preference thing. My preference is always keep the number of game objects in a project to a minimum. So I'd go with the 'has_flamethrower' variable route.

however each structure might need a slightly different system. For instance the sentry structure has a changing fire system, so if you later wanted to have an upgrade for a frost cannon both systems might fail (assuming you can't have both a flamethrower and a frost cannon) so I'd set it up like this:

enum sentryType {
      bullets, flameThrower, frostCannon,
fire_type = sentryType.bullets;
this way you can change the sprite and icons based on what fire_type this is.

That is a system you should use if there are multiple upgrades that can't be active at the same time.
If you have upgrades that can all be present simaltanously (for instance if the sentry has a faster fire rate upgrade and a more ammo upgrade then both upgrades can be used) then in this case it's fine to just have a single variable to store the upgrade.

EDIT: I realized it's actually a bad idea to change the object itself because if a building has any more than one upgrade then when you change it to a new object you'll have to remember all previous upgrades to the new object as well and that's just a hassle


Both options would work. I personally would go with destroying the first instance and creating a new instance. I would not use instance_change though unless you really understand how it works and are okay with the pros and cons.

Either method is very scalable. The second method is probably slightly more so though, unless the code for the first was very simple.

However, if I were really doing it, I would instead have my objects be more customizable. For example, I would have an upgradable parent object. This object would have children objects. And objects might be made of multiple things. For example, the gun of a turret might be a separate instance.

if clicked and can upgrade
run my script/user event
turret (child of upgrader_parent)
create event
create base gun type (a separate instance)​
my script/user event
destroy self
create better version of myself
general gun variables
machine_gun (child of gun_parent)
specific code
flame_gun (child of gun_parent)
specific code
and so on

Papa Doge

Thanks so much for the excellent suggestions and explanations!

I feel a little more confident in my approach now and have decided to follow the principle of "have the fewest number of objects possible" for a few different reasons but I like this principle and want to see how far I can take it. Both of your perspectives were valuable in helping me make this decision and I appreciate ya'll taking the time to lay out your thoughts.