The Component System (GDD#1.2)

By | 2013-01-19

Welcome to part 2 of “Game Development Design: The Component System”. Initially a second part wasn’t planned, but as I got a lot of feedback on part 1 asking about how self-attaching component systems work in detail, I decided to write a more detailed article about that.

Let’s quickly recall what a self-attaching component system is: The system consists of entities, properties and controllers. Entities can have none or any amount of properties, where every property is identified by a name and a type. Depending on what properties an entity has, controllers are attached to it.

Quick example: If there’s an entity with the property velocity, the controller Gravity will be automatically attached to it, because it requires exactly that property.

Before we start to go into detail, keep in mind that the GDD articles do not provide full source code. I believe in self-education and experimenting. Therefore I think that if you really want to learn and understand something, you have to play around with it.

GDD articles are mostly about software design for C++. I try my best to keep them independent, but since I’m a C++ programmer myself, using examples/code in that language just feels natural for me.

Now have fun with this article and drop me a line if you (dis)liked it or if you have any questions.

Properties

We’ll start with the smallest unit, the property. A property is simply a value that’s identified by a name (ID) and type. For example there might be a property called mass of type float. The first requirement when talking about source code is that we need a construct that can store any value.

In loosely typed languages like Python and Ruby, this isn’t a real problem:

However, in strongly typed languages like C++, we’ll run into problems:

When thinking a little more about what the requirements of a property are, then two things are clear: Each property has an ID, and each property has a value of a dynamic type. Since the value is the only thing that changes, we can come up with a simple class hierarchy:

Property

Property

Now it’s quite simple to store any type of value in a container, for example:

There’s only one real drawback: In C++ you can’t tell of what type an object really is. That’s why you have to downcast. Downcasting should be avoided where possible, because it often makes just no sense (you design class hierarchies to remove the need to know of what specific type objects are!). However in this case, it’s perfectly fine. Just think of it:

When you want to access a property, you expect it to be of a specific type. For example, if you want to get the value of the health property, you expect an integer:

Voilà, first topic covered, let’s move on!

Entities

The next thing in the self-attaching component system is the entity. An entity is simply an object; something that you need and use in your data model. An entity can be a car, a player, a gun etc. In the component system, the entity acts as a property container, or generally as the subject.

Implementing it should be really easy. Every entity stores properties and – only if you like – is identified by some ID. You also need to give access to its properties, like setting them, searching properties by name and type and so on.

There’s one special task that we’ll talk about later. For now, this is all we need.

Controllers

Controllers are by far the most important parts in the component system. They are responsible for the logic, for the stuff that’s about to happen: Physics, collision tests, shooting, walking and much more.

A controller in a self-attaching component system is never manually attached to an entity (hence the name self-attaching). Instead it defines a set of rules that have to be met in order for the controller to function properly.

For example, a gravity controller can only work if the entity it shall be attached to has a velocity property. Otherwise gravity can’t increase the entity’s velocity, and that’d be quite boring – at least for something like gravity.

Besides requirements it’s very important to understand that there’s one controller per entity. A lot of component systems work by calling controllers on a set of entities (e.g. by passing them as an argument to an update() function). Having one controller for each (suitable) entity has one very important benefit: The controller-entity pair is completely isolated. You can do whatever you want in the controller, it will never affect anything else than the entity it’s attached to. (There are also some optimization benefits, like caching property pointers; but this is just a hint for your implementation.)

That’s basically all you need to know for controllers. Let’s glue everything together now and talk about the special task I mentioned earlier.

Systems

I am really not sure if System is a good name for the gluing component of the self-attaching component system – if you have a better name, please tell.

A system in the component system is what manages entities and controllers, and which is responsible for attaching controllers to entities. Let’s take a look at a pseudo class diagram:

System class diagram

System class diagram

Some words about the map type: Keep in mind that controllers exist on a per-entity basis, therefore they must be mapped to entities – I am not talking about std::map here; I leave the implementation up to you.

So, what’s the hardest part? Definitely the attach process. Everytime an entity is created or its properties change, the system has to detach all previous controllers from it and attach new ones that match the entity’s new state. Example: An entity without any properties is created, and there’s one controller gravity which requires the property velocity. It’s not attached by the system, because the created entity does not meet the requirements. Now the velocity property is created, which will meet the controller’s requirements; therefore a controller is created and attached to the entity.

There’s one important question: How does the system know when an entity’s properties change? And this is the special task I talked about earlier. The system must somehow have the chance to subscribe to the entities and listen for property change events. This can be easily done using the observer pattern, for example.

Basically this is all you need for a working self-attaching component system. It should be relatively clear that you have to call every controller’s update() function when the system is run – otherwise nothing would happen.

Implementation tips

In case you don’t see a clear picture of what was described in this article, I’d like to give you some implementation tips for your experiments. At first here’s a nice diagram that’s great for getting an overview:

Overview diagram

Overview diagram

How to tell the system what controllers exist

The system needs to know what controllers it shall attach to entities, so at some point, you have to register them. A good approach would be to create controller factories just inside the system. Such a factory would simply check the controller’s requirements and create it when needed. Registering a controller might look like this:

How to specify requirements

I’d suggest to create a class function (static functions in C++) in each controller class that returns the requirements. For the requirements themselves, you’ll need another nice class. For example something that can be used like this:

Optimization/Performance

Please keep in mind that component systems are usually run at very high frequencies – normally at least at the speed of the current game’s FPS, but often higher, because physics or other logic subsystems require it.

That means you should spend some time thinking about fundamental ideas that speed up your component system. Use sequential arrays where possible, organize your data, avoid virtual functions where possible, use dynamic_cast in debug builds and static_cast in release builds. If you pay attention at such things, you will definitely have no problems running a component systems with lots of controllers and entities at high frequencies.

Conclusion

This article gave a lot of details on what a self-attaching component system is and how it works. It can be used for gathering ideas for implementing your own component system.

An implementation of this kind was programmed for the game FlexWorld – and we are quite happy to have it, as it allows quick prototyping and isolated business logic.

If you have feedback or questions, feel free to leave a reply.

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:

23 thoughts on “The Component System (GDD#1.2)

  1. resident-uhlig

    Is it right that the class System holds all Entities and Controllers of the whole world? Maybe “World” or “Universe” is a better name? It is a collection of world entities and natural laws (controllers).

    I think Controllers sounds too general because it is often used as a generic term in the description of design patterns. That is why I used “natural laws” above.

    What do you think of using more external links in your articles. For example you could link “observer pattern” to http://en.wikipedia.org/wiki/Observer_pattern

    Reply
  2. Stefan Post author

    Is it right that the class System holds all Entities and Controllers of the whole world?

    Yes, that’s correct.

    Maybe “World” or “Universe” is a better name?

    In my opinion both World and Universe are not technical enough. The component system itself is a pure technical detail, whereas “world” and “universe” are actual objects in the data model.

    I think Controllers sounds too general because it is often used as a generic term in the description of design patterns. That is why I used “natural laws” above

    Do you suggest “natural law” as a name? That sounds strange IMHO. 😉 I really can’t think of something that fits better than “Controller”. Yes, it might be confused with MVC or general code design terms, but in this case it’s just a good fit.

    What do you think of using more external links in your articles.

    That’s a good idea. I’m often too lazy to add hyperlinks to posts when they’re finished. But that’s only an excuse. I will try to add more of them.

    Thanks for your comment!

    Reply
    1. Stefan Post author

      Indeed, using Python you can quite often solve code design issues within minutes. 🙂

      Reply
  3. Greenie

    I thought it would be better for the description to have a more real world value.
    As I see it will probably end up having a property like “gravity=1”.
    As you can have something with velocity and you may not want it effected by gravity.
    So on and so fourth with “teleport=1”

    So the advantage over manually attaching controllers is that you have one central point that can universally change controllers or have special cases like when “helium=1” and “gravity=1″ use a different controller. or I suppose type=”Balloon”

    I would have thought Manager

     

    Maybe ControllerManager or a pretty standard name of EntityManager. Because it manages Entity’s behaviour. Sounds simple enough.

     

     

    Reply
    1. Stefan Post author

      As I see it will probably end up having a property like “gravity=1″.
      As you can have something with velocity and you may not want it effected by gravity.

      That would be just like manually attaching controllers.

      Automatic-attaching component systems have a very important rule: They define a consistent environment. It can be compared to duck typing in languages: If it looks like fish, behaves like fish and tastes like fish, it is fish. Same for the entities: If they have velocity and gravity (as in acceleration), they will be influenced by gravity forces.

      Instead of “disabling” gravity for each entity, rather think about what needs to be done to get the same effect. For example, to float in the air, you have to overcome the gravity forces, i.e. you apply thrust upwards until gravity = -thrust. So a solution would be to create a new “FloatController” that applies as much thrust as needed to overcome gravity forces. In fact it will try to control velocity in such a way that it’s equal to zero.

      One really has to drop old habits for this kind of component system — especially if you worked with the “more common” systems before, where you manually attach logic to objects, instead of defining their properties, resulting in behavior.

      Maybe ControllerManager or a pretty standard name of EntityManager. Because it manages Entity’s behaviour. Sounds simple enough.

      I always find the word “manager” in programming languages misleading. A manager, for me, is something like std::vector or any other container.

      Reply
  4. alexandre janniaux

    Well, I think that the word “system” fits perfectly in this case : you have the entities, and THIS “system” is really using the input data (entities) to provide the output data as any other system in any other domain would do it.

    In that way, I like very much the approach Bitsquid’s team has taken for their engine : you define entities in lua, you script them with node system or scripts (properties are exposed) and finally the engine takes all the entities as a blop of data (they use the structure-of-array writing) and is capable of splitting it to many bunch of data and calculating them separately in as many thread as we need without trouble. In that way, they only use primitive type (int, float, double, bool, string) and containers of primitive type to create the properties, and ID for entities. In a result, there is absolutely no boilerplate code and maintenance to do on the entity-component-system, and so it’s really fast in creating content AND in performance.

    In my opinion, such like a behavior is a very modern point of view that can justify the use of Data-Driven Approach in video game development, due to the need of fast iteration method to create contents.

    I used to study component system but now I don’t have the time anymore to do this, but I’m interested in the way you think of it. One thing very important in entity-component system is to stop thinking in OOP design, but think about what data we have, and what results any process on it should give. In that way, dependencies and conflicts are easy to find. In addition, if you need to use multicore-capability, I wonder how you would implement it in that kind of system, if you already think of it. 🙂

    Thank you for the share !

    Sorry for my bad english mistakes !

    Reply
    1. Stefan Post author

      Thank you very much for your comment.

      I’ve thought about doing a data-oriented approach, too. Indeed I made my head smoke for a couple of days, trying to think of a good solution to be 1. flexible and 2. data-oriented. However, regarding to the nature of vector data, which is normally aligned and well-defined in its structure, I couldn’t find one. A friend of mine is a big fan of data-oriented component systems, and he’s currently trying to figure out a cool way of doing it. In case he finds a nice solution, I might think about changing this too, because you can’t be faster than operating on pure data. 🙂

      due to the need of fast iteration method to create contents.

      I think there are a lot of ways to provide fast iteration. The described approach in my blog post at least has O(n) linear complexity. However it needs definitely more memory than a data-driven approach and some more CPU cycles for pointer dereferencing. Up to now I couldn’t see performance problems, it’s all performing very well.

      One thing very important in entity-component system is to stop thinking in OOP design, but think about what data we have, and what results any process on it should give.

      Exactly, and that’s also how this system works. Entities are pure data storages, and the controllers operate on them. It’s still very much object-oriented to me. I think both terms can greatly live in co-existence. 😉

      if you need to use multicore-capability, I wonder how you would implement it in that kind of system, if you already think of it.

      Yes, I’ve thought about it, but as long as I don’t need it personally, I won’t implement it (YAGNI). One problem that has to be faced is dependencies. Controllers might be dependent on the results of other controllers, so you’d have to make sure to synchronize all of that. An easy solution to this is to process each entity isolated. As most entities are not dependent on external stuff that changes during component system calculations, that’s fine for most cases, I guess.

      Thank you for the share ! Sorry for my bad english mistakes !

      Thanks for your nice comment. And no apologies for your English, I’m not a native speaker myself — we try our best, right? 😉

      Reply
  5. Thomas

    Great article!

    Just a few questions. As I understand it, each entity stores both a collection of attributes and ‘controllers’ that act on them. My first thought is that’s an awful lot of controllers, unless I understood it incorrectly would it not be possible (and more efficient) to have just one of every ‘controller’ and have the System, feed into it the entities that match the requirements? That would also help the System know what controllers are available as there would always be one instance of each. Unless of course there is a benefit to having unique ‘controllers’ which I’m failing to see.

    Finally, I’m not sure how this method would reduce boiler code maintenance – rather than change what to change. Even though the controllers self attach, factories would still be needed to create entities and apply their specific attributes, if you understand what I mean (it’s very late – 5AM-, so there’s a good chance everything I’ve said is incomprehensible/wrong 😀 )

    That’s all, very keen to start implementing a design similar to this for my current game engine.

    Reply
    1. Stefan Post author

      My first thought is that’s an awful lot of controllers, unless I understood it incorrectly would it not be possible (and more efficient) to have just one of every ‘controller’ and have the System, feed into it the entities that match the requirements?

      Yes, that’s perfectly possible. However I had the requirement that a lot of my controllers need temporary extra data for each entity, and I also wanted to avoid a lot of property look-ups. That’s why I’ve implemented it using one instance of the controller per entity, having member variables that 1) point to the entity’s properties (initialized once) and 2) contain extra data that’s not being stored as entity properties. If you can live without that, then I’d go with one controller, too. It saves memory.

      Even though the controllers self attach, factories would still be needed to create entities and apply their specific attributes, if you understand what I mean

      Yes, you probably want factories to initialize an entity’s property set, but you also have to make sure to stop thinking of “I want to attach controllers A, B and C”, but instead follow the “This entity has the attributes A, B and C” workflow. In the end nearly the same things happen, but it’s different by design. I wrote the following in the first part of the component system article regarding factories:

      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.

      Keynote: Factories that initialize controllers for an entity behave differently from factories that are initializing attributes. With the same attribute set you’re still able to exchange what controllers are going to be attached, by changing their requirements. This does not touch the entity’s attributes at all, which I see as a big advantage. So instead of changing all your factories (and their users) in case you want to change what components get attached, you simply change the requirements of the proper controllers or even add new controllers, without touching the attribute factories at all.

      That’s all, very keen to start implementing a design similar to this for my current game engine.

      Don’t forget to give feedback about how it worked out for you and thanks for your comment. 🙂

      Reply
    1. Stefan Post author

      There can be several properties for that. The easiest one would be “is_flying”. Another approach would be to check if the entity is not colliding with the ground, however that’s more suitable for jumping.

      Reply
  6. Marius Stärk

    Okay, but do you enable dynamic addition and removal of properties and if so how do controllers handle this? E.g. my entity has tires but one gets shooted off.

    Reply
  7. Chris M

    I have a few questions.

    If each entity has it’s own controller instances,  how do you manage interactions between entities? I read part 3 which talks about  messages. This seems OK for changes/events that can’t fail, but what if for example a controller wants to move an entity into a space already occupied? Or the user makes an invalid selection? It seems like the controllers would have to “know” that other entities exist and check for those kinds of interactions.

    How do you handle world/map/level data? Is that an entity with a big custom property with a big custom controller? It seems like it might be better if it existed outside of the entity system, but obviously it needs to interact with those entities’ controllers (which also relates to my previous question of how those interactions work).

    It sounds like a great idea, but it also seems like there are many practical issues that it would have. It would be great to see some implementation examples if possible.

     

     

     

    Reply
    1. Stefan Post author

      Hi Chris,

      it’s very important to understand that one can’t just go and implement *everything* as controllers or generally inside the component system. Controllers are encapsulated logic units, that perform a quite specialized task.

      In your mentioned example about an entity moving into another, there has to be some collision detection involved. The collision detection algorithm, together with the needed data, is usually not something you’d put into a component system. However you’d make a controller communicate with those external systems. Let’s say you’ve got a move controller that takes a velocity as input and modifies position as output. Before applying all the velocity, it has to check for collisions and possibly perform actions to solve a collision (collision response).

      So yes, a lot of stuff lives outside the component system, but you will often work with those things from inside the controllers. If you directly communicate with them or use an interface layer is up to you/your design.

      Reply
      1. Andrés

        Hello. These articles are truly great. I wish I had lessons like these at university.

        Well, I’d like to make sure I’ve got the concepts right:
        Suppose I have an entity called “Ball” with these properties:
        – Transform transform (position, rotation, scale)
        – vector2f velocity
        – float mass
        – bool player (or how would you define that some entity is controlled by the player?)

        Then, my System would attach these controllers to it:
        – Gravity (because it has velocity and mass)
        – Player (because it has player)
        – Move (because it has velocity and transform, and every update step it has to be moved in space by that velocity amount by adding it to its transform.position)

        So, Gravity and Player controllers would only modify the velocity property, but never move the ball; and the Move controller simply performs that move (modify the Transform) specified by the velocity. That way, Move would be the only controller required to communicate with the external collision detection algorithm, right? And the way to achieve that communication would be the message bus system.

        Does this look right to you?

        I’m sorry if all this looks kind of too obvious for you, I’m just trying to get the idea. Thank you!

        Reply
        1. Stefan Post author

          Hello Andrés, I’m glad that you like the articles. Regarding your question: Your concept looks nice, but I’d not use a “player” property. Whether an entity is controlled by a player or not doesn’t make it a different entity. A car is still a car, no matter who’s driving it. Therefore a player *property* does not make sense in my eyes.

          I’d rather create something that will set the velocity from outside. E.g. hold a pointer to the player entity and update its properties depending on user input.

          Reply
          1. Andrés

            Thank you for your answer!

            Well, I’ll think about it. It’s difficult to adopt a new entity design (this Component System) and suddenly need to get out of it. Some aspects are difficult to figure out where should be placed, and there exists the temptation to use the same system for everything even if it isn’t the best approach.

            I think now it’s time to start working on it!
            Thank you for your time and advice 🙂

  8. Veritas

    Very interesting article, I am doing something similar in a game I am making. Entities own Components, Systems remember the entities with the required components and act on them and an Engine class owns the Systems. Whenever you add a Component to an Entity the Systems check if they want to register it or not. This makes writing a new system as easy as writing a simple return statement and it’s main update loop. Adding new features simply requires you to make a new Component that holds the data and then write a System that operates on it.

    Reply
  9. Fredrik

    dynamic_cast is great handy things in c++. But reading your article i also realize that a substitute for Properties using dynamic_cast is to use visitor pattern. Whats your take on that ?

    Reply
    1. Stefan Post author

      I’m not sure how I’d apply the visitor pattern here. Can you give a concrete example?

      Reply
  10. Fredrik

    Hi Stefan

    I did the EPC test now, and truly the visitor pattern works as a substitude for the “controller”.
    https://github.com/utopiafx/epcvisitor

    It could be upscaled very easy, but there are some caveats there. The baseclass for visitor could very easy be to big, but in the other hand, nothings stops you to create more visitorbase-classes and add another attach in the components. Im aware also that some codes should also be more efficient, and built more saftely
    But this is a test only to show how a visitorpattern could fits in.

    So please take a look and please sends some feedbacks when you want.
    Im not sure if this is the best way to go yet.
    Also haven’t done any profiles or memleaks. So don’t take it as solid.

    Reply

Leave a Reply

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