5

My friend and I are building a mobile game and ran into the following design problem:

We will have many different types of units all with different stats and abilities. However, all unit types should have a few commonalities (for example, they would all have a totalhealth attribute).

We were trying to decide what the best way of representing these units would be.

My friend suggested simply making a new class for each unit type.

I feel that having hundreds of different classes feels wrong, but can't quite figure out what's so bad about it.

My alternative is to put the unit type information into either configuration files or a database (which will also solve the issue of enforcing every unit type to have a few common attributes with a schema). And then have a master unit class to instantiate types of units from the db.

What is the proper way of architecturing this?

3 Answers 3

7

Hundreds of classes are a problem simply because you will be forced to create an intricate inheritance hierarchy. The main principle that speaks against this is the Composition over Inheritance principle. Inheritance at such a large scale has large drawbacks, apart from simply having to know about hundreds of classes.

I also suggest that you create an interface for a Unit and shift your mental focus: think less about individual unit's stats and abilities, but more about general unit behavior.

For example, a unit may be able to move. In this case, you can add an orthogonal interface (i.e., it need not be inheriting from the Unit interface even) for Movable things, which allows you to query how far they may move, whether moving to x/y is valid, or to actually perform the move operation. Similarly, do not think about "this unit has x health", but think about units being damageable with the possible consequence of dying.

For the actual configuration of units you do of course need to provide these stats and abilities in some form of configuration (along with images/animations/etc.). For the retrieval, however, I suggest you take a close look at the Factory pattern.

Finally, you proposed a "master unit class", which reminds me to make you aware of the God object anti-pattern. Do not fall into this other extreme. There are many more choices than hundreds of classes versus one class. The whole spectrum in-between these is feasible as well, and certainly much more preferable than the extremes.

1
  • Ah by "master unit class" I meant something like a Factory pattern or a builder pattern, not a god object. Thanks for the feed back though, very helpful! Dec 17, 2013 at 19:04
6

Indeed, hundreds of classes feels wrong. It seems like your colleague wants to create a separate class, where in fact, you have separate instances of the same class. For example:

Animal
    Cat
        Black cat
        Brown cat
    Dog
        ...

is a wrong class hierarchy. One should instead limit himself to:

Animal
    Cat
    Dog

with Cat having a property FurColor.

In your context, this means that different stats and abilities would be presented as properties, while either all units sharing the same class, or having a few specific classes.

Now, where to put the information about the units? You have the following choice:

  • Hard code it,
  • Use configuration files,
  • Use database.

The first one has a major drawback: you have to rebuild¹ the application each time you want to change one aspect of a unit. This makes tweaking and customization practically impossible.

The second and the third one are the same thing, since configuration files are a database too. What should concern you is to pick a right level of strictness for your database. A relational database would probably be a bad choice, unless you're absolutely sure you won't change the schema over time. If the choice is between a NoSQL and, say, a bunch of XML files, see what's easy and more flexible for you; also, don't reinvent the wheel.


¹ Build ≠ compile. If you use a dynamically typed language, you still have to run tests at build a stable version on every change you make.

2
  • Let's use pokemon as an example. There's hundreds of pokemons. We can't simply have a Pokemon class and have hundreds of instances, since we have to store the fact that a "pikachu" (for example) is lightning themed into the code somehow. Dec 17, 2013 at 19:05
  • @RazorStorm: what about Theme property which will be equal to Themes.Lightning? Dec 17, 2013 at 19:43
0

The proper way depends on many factors, but a big one among them is how these units differ from each other.

If the units only differ from each other in the (initial) values that they have for their attributes (which all are common to all the units), then your idea of using configuration data is a good way to easily create many different units.

On the other hand, if the different units need to respond differently to interactions with other entities in your game (where different response means writing different code), then your best bet is to use different classes for the different units, that all derive from a common base class that defines the common attributes and method interfaces.

As a third possibility, you might have a mixture of the two options. In that case, you should also use a mixture of the designs: different classes for the groups of units that show different behaviour, with configuration data to make up the different units within each group.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.