# initialising units' properties & upgrades

I'm making a RTS in which units can get several cyber-upgrades (individual, not as a global tech-tree upgrade like in most RTS games) before they're created. Now, I'm trying to decide how to do this, logic-wise. The system I have right now is that each unit type (walker, car, etc.) is a class, and when I initiate an instance of the class I add all the modifiers to the constructor, and let the constructor handle all the modifications.

This seems to me like the wrong way to do it - it means copy-pasted code in all the constructors. The other idea I had was to have each modification as a static method that takes a Unit class and modifies it - but the modifications might need access to private memebers (health, speed, etc.), and if I write the methods per-class, again I achieved copy-pasted code. As far as I know there's no way that a external static method can access private fields, and I don't want to create properties for every field, so as not to make the classes too cumbersome to use.

Example, to clarify: let's say I create a new Agent, and I want him to have bionic feet (+5 speed), x-ray vision (change of sight-function) and armored body (change of hit effects). I could use a constructor like Agent(speed, vision, armor), but if I'd later want to create new upgrades, such as fast reactions (+5 initiative), I'd have to change the constructor's signature. I could use a constructor like Agent(List), and then in the constructor create a giant swtich/case for every available upgrade, but then, I'd have to copy it also to the constructor of Vehicle, and make sure I update both of them, exactly the same. What I'd like to do is have a basic constructor and after it have a:

internal delegate void Effect(Unit ent);

void setup(List<Effect> list)
{
foreach(Effect effect in list) effect(this);
}


method, and then run every effect in the list on the new Unit, but then the Effect can't access the unit's private members.

Is there an elegant solution to the problem?

Using your idea of a switch statement to apply the upgrades, you could achieve what you want here by having the walker and vehicle classes derive from a parent "Upgradeable" or "Stat" class. This can be used to handle all of the stats for both unit types, which will make changes easier to maintain.

For example:

public enum Upgrade {
ARMOUR_MKI,
ENGINE_MKII
}

public class Upgradeable {
protected int hp;
protected float speed;

switch (u) {
hp += 100;
break;

speed += 5f;
break;
}
}
}
}


Then derive your other classes from this:

public class Walker : Upgradeable {
hp = 100;
speed = 4f;
}

// Class Specific Stuff
}
}

public class Vehicle : Upgradeable {
hp = 200
speed = 2f;
}

// Class Specific Stuff
}
}


This provides the type of interface you want, whilst maintaining protection of your object's members and upgrade method calls. The centralisation of the Upgradeable class also makes maintainability of the upgrades between unit types much simpler. And with the ApplyUpgrades method calls in the derived classes, you can implement specific upgrades or effects per-class too.

• This seems like a sound idea, but isn't the loop in Upgradeable a bit heavy, computability-wise? If I have n potential upgrades and m actual upgrades to a unit, then every unit creation is O(n*m) actions. Now, m usually will be negligible, but I wonder - if n grows, isn't this a bit too complex? Apr 25, 2012 at 13:57

There are some things to consider: Are these upgrades just about modifying values or do we need things like adding new visual effects or new behavior when something is triggered. Jason's solution is alright for the limited requirements of the former. Although you would want to keep list of upgrades available too.

For the latter requirements, there are many different design patterns available. For instance, you could have base class Upgrade (or a more general name like "Attachable") which has events OnAttach or OnDetach which are evoked upon adding the upgrade to an object, and then it adds handlers to the object's events; and later removes them OnDetach.

Latter solution could be unwieldy and more inefficient if your requirements are smaller. Optimization is probably your least concern for now anyway.

And you can have some Factory-objects or methods to ease the generation of these composite-objects.

Why don't you add Effects as a property of your Unit class?

Effect armor = new Armor(5);
Agent a = new Agent("Name");