The Component System (GDD#1.1)

By | 2012-11-14

Game development is a fascinating and fun thing a lot of people enjoy. Some are even making a living out of it, others do it as a hobby. For whatever reasons you are programming games, I’d like to congratulate you for choosing one of the hardest and most difficult areas of programming. Programming games involves a lot of topics, for example:

  • Fast algorithms
  • A lot of different sub-systems
  • Real-time data processing
  • Graphics rendering
  • Audio processing
  • Game design/logic
  • Data (De-)serialization and -synchronization

When asking people why they are making games, you often get a whole bunch of answers: “I like playing games!”, “I’ve always had that special idea I wanted to realize!”, “I like the challenge of making games” and much more. One thing however is for sure: It’s tough. It’s really tough. If you’re new to game development: Prepare for a wild ride with ups and downs, doing a lot of research, having motivation problems — and much more. The Game Development Design series is mostly for developers who are doing game development in their free time or as some kind of indie developer. Professional — that means “I do it for the money only” — programmers usually do not care so much about elegant and passionate code design. And that’s what this series is about: Experimenting with modern approaches of doing things, having no problems doing big chunks of refactoring — or in general: Working with lively source code.

All GDD articles will cover one topic of game development. I do not claim that what you read here is the best of the best. However I can guarantee that a lot of effort had been put into tailoring the solutions I want to show here. Nevertheless: If you find errors or don’t like what you read, then please leave a comment so that I’ve got the chance to improve this. When we look at source code, it will be either pseudo or C++ code.

The first part of the GDD series will cover how to build an interesting component system for your game. It will show what popular systems exist and what might be a very interesting alternative.

The Past: Class Hierarchies

When object-oriented programming (short: OOP) got very popular, many programmers tended to overuse some techniques and design patterns. One of them is called inheritance; something that’s still very popular today. Of course that’s for a good reason, because inheritance means that we can take a base functionality and extend it, thus resulting in extensible code.

The following hierarchy seems to be quite natural: There’s a Tree and a TreeWithLeaves.

Except the visual representation, they’re exactly the same. The tree with leaves shows – guess what – leaves, maybe animated using timers, whereas the normal tree is a static object. If you later decide that you need another type of a tree, for example a TreeWithLeavesAndApples, you can extend TreeWithLeaves with the extra functionality:

The same procedure continues with a tree without leaves but with apples, later peaches etc.:

You may already have noticed the problem: The more variations you want to support, the deeper the hierarchy will be. That’s already bad enough, but you will also be writing a lot of duplicated code: TreeWithLeavesAndApples and TreeWithApples have different base classes, therefore the apple functionality has to be implemented multiple times. You could establish multiple inheritance:

But as we know: Multiple inheritance is really bad, because it can lead to severe problems (e.g. in the example above, TreeWithLeavesAndApples inherits Tree twice!).

Conclusion: Whatever you do with inheritance, it will result in monster hierarchies which are not flexible and very hard to maintain.

A Popular Approach: Constructed Entities

Especially game developers were looking for new ideas for loosen up the connections between classes, i.e. eliminating monster hierarchies. One approach that’s still widely used is constructing entities.

Instead of inheriting from one or multiple base classes, developers tried to construct entities out of components. To stick with the tree example from above: The TreeWithLeavesAndApples would now be a general entity with the components Tree, Leaves and Apples.

The advantage should be clear: Compositions of components can be completely customized. I can simply say: I need a tree with leaves, one with apples and one without any further things.

Unfortunately the implementation of such a system is not always clean. Typical implementations look like this:

Granted, this is already much cleaner than having big hierarchies, because it’s possible to create dozens of different entity combinations without changing source code at all (except constructing the entities, of course). However there’s still a drawback:

You somehow have to manage the construction of entities. Some implementations use entity factories to overcome this problem. They define a set of template entities which are used to construct entities with a specific set of components. The above example would be added to a factory like this:

This makes constructing entities easier, and it also allows the developer to define a set of entities that are interesting for the game that’s being developed. For example, if one’s developing a zombie game, you might need create_zombie() and create_weapon() and create_player().

However you still have to maintain all the factories you’re going to use, and in case you change components, you also have to adjust your factories. This is annoying, but avoidable!

An Automatic Approach: Self-Attaching Components

Now let’s talk about something that solves the previous described problems, which are: Monster hierarchies and annoying code maintenance.

When talking about entities in a game and the real world, they can be split into two parts (at least in the area which is interesting for us): Properties and behavior. Properties might be color, size, weight etc, and behavior walking, jumping etc. The interesting part is that properties and behavior are very tightly connected. Depending on available properties we can tell of the possible behaviors.

Let’s do a little example: We define that every player who has legs, weight and some kind of walking power is able to walk around. That means the walk behavior requires those properties in order to work. Otherwise the player can’t walk.

The very big advantage over the other component systems is that a component (behavior) defines what properties it requires in order to work. If an entity has the properties, the component can be attached and start its work. What does this solve in detail?

  • Every component exists on its own, completely isolated.
  • Entity<->Component connections don’t have to be maintained manually (in a factory for example).
  • Instead, components automagically connect to entities which match the requirements.

The result: An extremely flexible and extensible component system, which also feels very natural when designing components. You can fully concentrate on writing the components themselves without the need to adjust and maintain boilerplate code. We still have to decide which entity gets what properties, and this is indeed similar to the entity construction factory. However properties do not define behavior, so that part is completely separated into components.

Another advantage of this approach is that it can be easily extended externally, for example by scripts. You could either allow to change entities’ properties which results in different behavior, or you could allow to write custom components that plug into the existing system without any problems.

Conclusion

This article described three different approaches for writing game logic. An old approach using inheritance, a popular approach using constructed entities and a relatively new and flexible approach with self-attaching components.

In my opinion, everybody should really forget about inheritance for game logic hierarchies/systems. It’s not flexible and needs a lot of work for making it work and maintaining it. Constructed entities are already nice to use, as they are modular and changing single components is not a big deal. However using self-attaching components reduces the boilerplate code to a bare minimum and looks at the logic stuff from a different perspective: You primarily do not define logic, you set properties which result in behavior.

Feedback on this article is greatly appreciated, thanks for reading!

If you like the GDD articles and would like to support the author, consider buying the PDF/EPUB/MOBI version in a pay-what-you-want fashion:

Category: GDD

13 thoughts on “The Component System (GDD#1.1)

  1. Mercy404

    I implemented a component based entity system in a hobby project of my own recently.
    I ended up calling Behaviors “Systems” (Animation System, Movement System, etc) and Data “Properties” (Render Properties, Spatial Properties, etc). There is no class for an entity, instead they exist as an unsigned int (auto-incremented ID).

    Systems are given a list of Properties an Entity must have have before it will accept it.
    Properties are templated unordered maps of Instance IDs and a structure with the desired data. This lets multiple systems (behaviors) share the same data (properties) quite easily.

    I also added the concept of “Prototypes”, which you give a list of Systems to, and call MakeInstance(). It will create all the required blank properties the systems need, and link your entity to them. It also allows you to define default properties to use instead of blanks, so you can easily create multiple identical entities.

    Reply
    1. Stefan Schindler Post author

      That sounds interesting. Some questions though: If an entity in your implementation is an unsigned integer, how are properties associated with it? For example, if I want to assign the properties “color” and “weight” to entity #37, how would that look like in your implementation?

      Reply
      1. Mercy404

        Individual variables are grouped into “Properties” like so:
        http://pastebin.com/Mvex7vns
        Then placed in unordered maps keyed on the instance ID in the gamestate class.
        There’s a bit of legwork involved when you create a new property type at the moment, you have to add an enumeration, create the class, add a map of them to the gamestate class, then create a case for the new enumeration in the System and Prototype base classes to tell them which gamestate object to look for that property type in.

        After it’s all setup though, creating prototypes and accessing the properties of instances is relatively painless: http://pastebin.com/bz0d3PAg

        Not the most elegant thing ever, I’ll be the first to admit, but it has worked fairly well for me so far.

        Reply
        1. Stefan Post author

          I see. Unfortunately the amount of boilerplate code and maintenance required to keep your approach in a consistent state is relatively high. You named it yourself: You have to maintain an enum, create the class itself, maintain a mapping and a switch(). It works, but it requires you to follow steps manually to keep your code clean (i.e. when removing a component, you have to clean up the enum etc.).

          Reply
          1. Mercy404

            Since you only have to add a bit of boilerplate code when creating new Property Types, I find that it’s worth the hassle. I quite dislike the GetComponent(type, name) paradigm, so adding three lines extra lines to two additional files is a good trade-off for me.

          2. Stefan Post author

            There are other solutions than GetComponent( type, name ). 😉 My opinion is that if you can get rid of most of the boilerplate code, why not doing it?

  2. Rosme

    Now that is interesting. I always end up being all messed up in my game dev. I really hope you’ll continue and that it will help people like me, who are learning slowly but surely in the process of making a game. Keep going. Nice Article.

    Reply
  3. Vittorio Romeo

    You talk about “Self-Attaching Components”, and it sounds really interesting… can you show an example as you did for the EntityFactory?

    Reply
    1. Stefan Post author

      More details will be covered in the second part. However I’m not going to write a full example, that’s up to the developer, e.g. you 😉

      Reply
  4. Zarkonnen

    This is a very nice explanation of how to do a good component-based system. 🙂 Another advantage I’ve found to making game entities have properties like that is that it makes it easy to serialize the entities.

    What I’ve found works well in Java is some clever usage of the type system, like to:

    Then you just define Property constants, and you get a typesafe property system. 🙂

    Reply
  5. Onion

    Very informative, nice.

    I have one question though. You split up the behaviour in ‘components’ and the data in ‘properties’. I’ve read quite a few sources that mention ‘systems’ and ‘components’ in which components hold the data and systems define the behaviour – and the systems are indeed automagically connected to all entities holding the necessary components.

    Your solution seems extremely similar except it’s using different terms, am I correct?

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *