Component Based Engine Design

What is Component Based Design?

Component based engine design was originally pioneered in order to avoid annoying class hierarchies that inheritance introduces. The idea is to package all functionality of game objects into separate objects. A single game object is just a collection of the components, as so the components of a game object define it’s behavior, appearance and functionality. This is perfectly fine, though there are plenty of resources out that talk about this topic. However I’d like to take a step back and start from the top.

It should be noted that the implementation presented here is just one way of going about things, and comes directly from my highly subjective opinion. Perhaps you as a reader can come up with or know of better solutions or designs.

Here is an example game object, note that the game object is generic and simply contains some components:

The Actual Engine

The engine of a game can be thought of as a manager of systems. As to what a system is, we’ll get to that later, for now think of a system as either Physics, Graphics or AI. The engine ought to have a main loop function, as well as an update function. The update function calls update on all contained systems in a specific order. The main loop function is just a small infinite loop that calls update.

Often times the main loop will deal with timestepping itself. Have a look at the linked article to learn more about proper timestepping.

It is important to have your engine expose the update function, as sometimes your engine will need to be compiled as a static library and linked to externally. In this case the main loop of your simulation may reside outside of the engine library altogether. A common usage I’ve seen for this sort of design choice is when creating an editor of some sort, perhaps a level or content editor. Often times these editors will have a veiwport to preview the game, and in order to do so access to some sort of engine update function is necessary.

Beyond containing and calling update, the Engine also forwards global messages to all the systems. More on messaging later.

Singletons?

Creating more than one instance of an engine should never happen. The question of “should I make this a singleton” will sometimes arise. In my experience the answer is often no. Unless you’re working on a large team of programmers where the chances of some moron making an instance of some Engine or System class, making things a singleton is just a waste of time. Especially if retrieving data from that singleton incurs a little bit of overhead.

Systems

Each system in the engine corresponds to one type of functionality. This idea is best shown by example, so here are the various systems I usually have in engines I work on:

• Graphics
• Physics
• GameLogic
• Windowing/Input
• UI
• Audio
• ObjectFactory – Creates objects and components from string or integral ID

Each system’s primary functionality is to operate upon game objects. You can think of a system as a transform function: data is input, modified somehow, and then data is output. The data passed to each system should be a list of game objects (or of components). However a system only updates components on game objects, and the components to be updated are the ones related to that system. For example the graphics system would only update sprite or graphics related components.

Here’s an example header file for a system:

The naive approach to a system update would be to pass a list of game objects like so:

The above code is assuming the ObjectFactory contains all game objects, and can be accessed somehow (perhaps by pointer). This code will work, and it’s exactly what I started with when I wrote my first engine. However you’ll soon realize the folly involved here.

Cache is King

That’s right, those who have the gold makes the rules; the golden rule. In a more serious sense, cache is king due to processing speed related to memory access speed. The bottleneck in all engines I have ever seen or touched in the past couple years has been due to poor memory access patterns. Not a single serious bottleneck was due computation.

Currently modern hardware performs very very fast. Reaching for data in memory (RAM, not just hard disk) is orders of magnitude slower. So caches come the rescue. A cache can be thought of, in a simplified sense, as a small chunk of memory right next to the CPU (or GPU). Accessing the cache memory is way faster than going all the way out to main RAM. Whenever memory is fetched from RAM memory around that RAM location is also placed into the CPU cache. The idea here is that when you retrieve something from RAM the likelyhood of requiring to fetch something very nearby is high, so all the data in that area is grabbed all at once.

Long story short, if you place things that need to be accessed at around the same time next to each other in memory, huge performance benefits will be reaped. The best performance comes from traversing memory linearly, as if iterating over an array. This means that if we can stick things into arrays and traverse these arrays linearly, there will be no faster form of memory access.

Fetching memory that does not exist in the cache is called a cache miss.

Cache and Components

Lets revisit the naive approach to updating systems. Assuming a system is handed a generic game object, that system must then retrieve its corresponding component(s) to update, like so:

As this loop is run the memory of every game object and every component type that corresponds to the system is touched. A cache miss will likely be incurred over and over as the loop runs bouncing around in memory. This is even worse if the ObjectFactory is just creating random objects with new, as every memory access to every object and every component will likely incur cache misses.

What do? The solution to all these memory access problems is to simplify the data into arrays.

Arrays GameObjects + Components

I suggest having every game object exist within a single giant array. This array should probably be contained within the ObjectFactory. Usage of std::vector for such a task is recommended. This keeps game objects together in memory, and even though deletion of a game object is of O(n) complexity, that O(n) operation traverses an array, and usually will turn out to be unnoticeable. A custom vector or array class can be created that avoids the O(n) operation entirely by taking the element at the end, and placing it into the deleted slot. This can only be done if references into the array are translated handles (more on handles momentarily).

Every component type should be in a giant array too. Each component array should be stored within their respective systems (but can be “created” from the Factory). Again, an array like data structure would be ideal.

This simple setup allows for linear traversal of most memory in the entire engine, so long as the update function of each system is redesigned slightly. Instead of handing a list of game objects to each system, the system can just iterate over its related components directly, since the components are stored within the systems already.

So, how are Game Objects “handled” now?

Since components have been moved into large arrays, and the game objects themselves are in a big array, what exactly should the relationship between a game object and a component be? In the naive implementation some sort of map would have worked perfectly fine, as the memory location of each component could be anywhere due to the use of new calls. However the relation isn’t so carefree.

Since things are stored in arrays its time to switch from pointer-centric relationships to handle based relationships. A handle can be thought of in its simplest form an index into an array. Since game objects and components are stored in arrays, it is only natural that to access a game object you do so by index. This allows for these giant arrays to grow and shrink as necessary without obliterating dangling pointers in the rest of the program.

Here’s a code example:

As you can see, an array of handles is stored to represent the containment of components. There is one slot in the array for each type of component. By design this limits each component to be of unique type within a game object. Each handle is an index into a large array of components. This index is used to retrieve components that correspond to a game object. A special value (perhaps -1, or by some other mechanism) can be used to denote “no component”.

Handles can get quite a bit more versatile than just a plain ol’ integer. I myself created a HandleManager for translating an integer into a pointer. Here’s a great resource for creating your own handle manager.

The idea of translating a handle into a pointer is such that once the pointer is used it is not kept around. Just let it be reclaimed back into the stack. This makes it so that every time a pointer is required there is a translation of handle to a single pointer somewhere in memory. This constant translation allows for the actual pointer value to be translated to, to be swapped for another pointer at any time without fear of leaving dangling pointers.

Where does the Code go?

Code for update routines can be put into either systems or components. The choice is yours entirely. A more data oriented approach would put as much code into systems as possible, and just use components as buckets of data. I myself prefer this approach. However once you hit game logic components virtual functionality is likely to be desired, and so code will likely be attached directly to such components.

The last engine I built used the naive approach to component based design, and it worked wonderfully. I used a block allocator so cache misses weren’t as high as with raw new calls.

The point is, do what makes most sense and keep things simple. If you want to store routines within your components and use virtual function calls, then you’ll probably have trouble storing things in an array unless you place all memory in the base class. If you can externalize as much code from your components as possible, it may be simpler to keep all your components in an array.

There is a tradeoff between flexibility and efficiency. My personal preference is to store performance sensitive components in huge arrays, and keep AI and game logic related things together in memory as much as possible, but not really stress too much about it. Game logic and AI should probably just be rather flexible, and so details about memory locations aren’t so important. One might just allocate these types of components with a block allocator and call it good.

Messaging

The last major devil in an engine is messaging. Messaging is transferring data from one location to another. In this sense the most basic form of messaging is a simple function call.

Taking this a step further, we’d like to be able to send messages over a connection in a generic manner. It should not matter what type of message we send; all messages should be sent the same way to reduce code duplication and complexity. The most basic form of this is dynamic dispatch, or virtual function calls. An ID is introduced to the message so the internal data can be typecasted to the correct type.

Still, we can do better. Lets imagine we have a sort of GameLogic component or system. We need a way to send a message to this object that contains some data. Lets not focus much on memory access patterns, as simplicity and flexibility are key here. Take a look at this code:

This code highlights the usage of messaging quite well. Say the player emits some messages as it walks around, perhaps something like “I’m here” to all nearby things in a level. The player can blindly send these messages across the SendMessage function without caring about whether or not it will respond or do anything. As you can see, the implementation of the SendMessage function ignores most message types and responds to a few.

In this example when the player nears the treasure chest it will glimmer a bit. Perhaps when the player gets closer it glimmers brighter and brighter. In order to do so, the MSG object sent to the treasure chest ought to contain the player coordinates, and so it can be typecasted to the appropriate message type.

The eActivate message may be emitted by the player whenever they hit the “e” button. Anything that could possibly respond to an eActive message will do so, and the rest of the objects receiving the message will safely ignore it.

This type of messaging is simple and easy to implement, quite efficient (if a block allocator or stack memory is used for the messages), and rather powerful.

A more advanced version of messaging makes heavy use of C++ introspection. A future article will likely be devoted to this topic, as it’s a hefty topic altogether. Edit: Here’s a link to a slideshow I presented at my university.

Resources:

Share

59 thoughts on “Component Based Engine Design”

1. damo

Brilliant article, I’ve researched a lot about component based systems but this really clarifies some things about the implementation of it

2. Manuel

Hi and thanks for the nice article!

I was going to ask: how are you going to maintain the rendering order for objects such as trees with opaque foliages? That would need some special attention on their drawing order to get them right, so wouldn’t the cache-friendly data simplification make it more difficult to do?

1. Randy Gaul Post author

Not really, afaik. Now I’m not a graphics programmer, but my understanding is that sorting can be used to achieve a correct draw order. Since all handles are array indices swapping around memory within the array and updating indices is no big deal.

3. Manuel

I mean, building indexed sublists for the renderer could be a way, but also this imply keeping them sync’d with the hierarchy as well..

4. CBS

Very good article, but i haven’t understood very well the cast to

since   LocationMSG is a struct without the id  filed and in your previous code you have used the same pointer in this way  msg->id

1. Randy Gaul Post author

Oh thanks for commenting. That was a typo. The message should definitely have an ID at the top of it’s memory. Inheritance would be a less error-prone way of ensuring that the memory of message types contains that 4 byte integral ID at the top of their memory locations.

5. Simon

Great article Randy.  I have been researching component systems recently and trying to develop one myself.  This is probably the most clearly written article describing a component based system.

I was wondering if you have any sample code you could provide?

How fine grained would you make the components as well?  Would you have a Location component which stores the objects Position and Velocity for use by the physics and graphics system?  Or would you split these up into smaller components, Position component and Velocity component?

Thanks, and keep up the great work.

1. Randy Gaul Post author

For physics specifically there will probably be: RigidBody, Shape. Then for graphics there would probably be (for 2D game): Sprite. Sprite would contain a Matrix4 for transformation of model to world. The RigidBody would contain transform for model to world as well. The data needs to be duplicated to allow graphics and physics to transform arrays of data linearly.

I am currently writing an open source game engine/library. I have no idea when it will be done though :)

6. mark

Good article.

Where I get a little confused with the component based-design you suggest is how to build systems that require access to other systems.  AI for example needs to be aware of the surrounding environment.  However, since it’s only passed the object to act on how do you find out about the other nearby objects?  Does it directly access the gamestate?

1. Randy Gaul Post author

Yeah, you’d need to access information gathered by other systems. Some form of broadphase query or messaging system would let an AI or logic system know about adjacency information.

7. Lokked

Randy, the couple examples was exactly what I needed to get started. I understand the concept of ESC, but could not figure out what I need to do to start to change the bloated Hierarchy I’ve got going on in my application, to one utilizing ESC.

Thank you so much!

8. Federico D'Ambrosio

Hi Randy, this is really a great article: currently i’m working with a friend on the development of our first little game and your article has been a major help in structuring our game engine in a ECS based way.

It’s all very clear about what you’re doing and how you’re implementing it, but I can’t understand the use of the float variable dt you have used in update functions and what should it be its real purpose.

1. Randy Gaul Post author

This is delta time passed around for a game loop update. It is a measure of the time elapsed by the previous frame. Usually it is variable for game logic and constant when determinism is required (like for physical simulation).

9. Jon Schultz

I’m fairly new with programming (so I’m sorry if this is a painful question!).

With regards to contiguous memory and taking advantage of processor cache and branch predictor, does this mean that the Arrays of components (which are Arrays of pointers to the New’d Components, right??) are what needs to be contiguous? Or is it the objects on the heap themselves that need to be contiguous?

I have my implementation framework complete, but now I’m wondering if I need to implement some sort of Memory Pool to keep objects in contiguous memory.

Right now, on engine initialization, I preset the size of each std::vector to some upper limit (power of 2), and these vectors are of std::vector<component*> (I’m switching to boost::ptr_vector soon). If an object factory is creating entities/components at varying points, won’t New just place the data at the end of the Heap or in some gap it finds?

Please clarify if this is actually something I should be considering.

If it really is that the objects on the heap need to be manually forced into contiguousness, I’d like to have 1 allocated pool per component so that the System ‘Update()s’ operate on this section of memory.

Thanks much.

1. Randy Gaul Post author

Good question. The array of components needs to be actual components next to each other in memory. If this were arrays of pointers of new’d components, then each time you access a component the memory will be located at wherever new actually allocated memory from (unknown and likely very far away from other new calls).

Yes, the objects themselves need to be next to each other in memory for maximum performance. An array of pointers will be pointing all over the place if each pointer is pointing to separately allocated memory.

Hope this helps!

10. Jon Schultz

I can create entities and components at runtime, at varying points in time and newly created entities/components are appearing in contiguous memory space.

I’ve set my Systems so their Update() function requests a vector of applicable components to operate on, from a ComponentManager object. This is because I read above that it doesn’t make sense to operate on the entire array of Components as some may not all use the applicable Component (ie Not all Entities will have an AI Component, or an Animation Component).

For example, ComponentManager creates a Pair of RenderableComponent* and PositionComponent* when an Entity is connected with both of the applicable Components. This is done when the Components are connected or disconnected. This Pair is placed in a vector with all the other Entities’ Pairs. To save processing time, this list is only updated when an Entity has a Renderable/PositionComponent added or removed.

Now I realize that with a list of pointers to these components, because the components are each in their own vector of component type, I can never use vector.erase(), as this will cause the pointer list to be wrong, and if I instead choose to keep track of inactive components and reused inactive objects, I will have to come up with a different scheme for adding Entity/components, besides vector.push_back().

Does it need to be this complicated or am I worrying to much about saving processor cycles when it comes to iterating through vectors. Perhaps I could just rebuild the whole list of System-specific components each frame.

1. Randy Gaul Post author

Well you definitely don’t need to worry about performance at all, as suggested in the slides I link to at the bottom of this article. However if one wants to pursue a more data oriented approach (like the ever popular entity component system model suggests), then contiguous arrays is preferred. In this case the arrays need to shrink and grow as necessary. You cannot store a pointer into this array permanently, as a shrink or growing operation will move the array from spot to another. To resolve this you represent relationships between game objects and components through handles. See the handle section in this article. Whenever an object is moved in the array, you will need to update the pointer stored in the HandleManager.

11. Vincent

I’m a little curious about the way systems iterate over all game objects in the world and find those they need. Do you have a sample of that code?

1. Randy Gaul Post author

It definitely depends on what kind of system we’re talking about. For my own graphics (within https://bitbucket.org/rgaul/sel) I just have a stored array of all sprites. Graphics then loops over all the sprite components and renders them. For game logic I keep a linked list of all game logic components and just loop over those. The game logic components can access data in other components of the object by doing something like: owner->GetComponent( type );

Does this help? I suggest checking out the engine I linked for a working example (I’m actually actively working on it right now).

This whole approach is new to me, I discovered about a week ago and it’s sort of blowing my mind. I remember being tasked with making games while at Uni using an OOP approach, and I always ended up with large hierarchies of classes and a lot of horrible problems with updating all game objects at once. It never did feel quite right.

I have a couple of questions though. I understand there are different ways to do this, but in your approach, it seems like each system has a list of what components it needs to update, correct? Or is, for example, the RenderingSystem given a list of the relevant components every time it’s called in the main loop? If it’s the former, how does each system add and remove components that are created or removed in other systems?

My main roadblock here is I don’t actually understand where components are created initially and how systems ‘know’ what to act upon. Where is the ‘master list’ of all components actually kept? The engine class or the systems class?

1. Randy Gaul Post author

This is a good question and I’m glad you’re asking. Shortly I will be posting a good solution to this topic in the form of an article. It is entirely possible to just let each system store the components directly within, perhaps with a std::vector. However a more elegant and useful approach can be used called Spaces. For now you can check out a good video my colleague Sean Middleditch posted on youtube.

You can see an implementation of spaces in my own open source engine SEL: http://www.randygaul.net/projects-open-sources/game-engine-sel/

13. damir

Hello, thanks for a good article.

I have one situation that I don’t know the best solution for. Suppose you have a car (Entity) with 4 wheels (also Entities).

We need to mark the wheel entities as childs of the car entity, because AI might want to shoot the tyres, or physics would need to check the force the wheel is generating. Maybe attach a ‘parent’ Component to wheels, which holds reference to parent entity? This way we can also decouple the wheel fairy simply by just removing the parent component. Or should we make a ‘car’ Component which would hold references for wheels (seems too much specific)?

Should the position component be absolute, or relative (more likely) to parent? All systems would need to follow this rule. We would probably need to send an event on decoupling, so physics can break constraints and make the local-to-world position transform, and graphics can make proper changes to the render graph.

There’s also an issue of performance – ‘get me all childs of this entity’ would not be very fast. Maybe have a cached array of childs on each entity?

1. Randy Gaul Post author

I think this sort of hierarchy can be best achieved through some form of a scene graph. This can be considered one reason why a pure ECS is a poor design. It should be very easy to specify a hierarchy of transformations if this is something commonly needed in your game, and it should be very fast. This would mean that transformations from child to parent are relative to the parent.

A scene graph can be an engine feature, or purely a graphics feature, or only implemented for the physics. You can have some sort of scene graph in physics and an entirely different one for graphics. There are a lot of ways to go about this.

14. Mitchell Stokes

It seems to me if you attempted to run the component updates in parallel that you would run into issues with false sharing since the components are meant to be tightly packed in cache. If at least two components are on the same cache line (which seems to be the goal here) and those components are updated by different threads, a write to one component would invalidate the cache line for other threads. Any thoughts on this?

1. Randy Gaul Post author

I imagine this would be an issue in any game engine or multi-threading scenario, not just one regarding components or arrays. As with any multi-threading problem it will help to have uniform isolated data that can easily be transformed. I imagine a simple task manager with a dependency graph can handle most common requirements. However the performance benefits of going crazy with threading transformations will probably be negligible if physics is done in a separate engine, and graphics is done within its own library; usually systems like these have their own internal form of data oriented design implemented, and any components involved in these are just light wrappers.

15. jriv

After reading so many game design articles praising the Singleton as God’s own pattern and others arguing about it being a syntactic sugar for creating global variables, I absolutely bust out laughing with your take on them at the beginning. :P

Great article.

16. Erik

Excellent article Randy, thank you very much. =) I just have a few questions:

In your designs, do each of your systems maintain component data themselves? That is – for a hypothetical ‘Movement’ system that operates on entities having both ‘Position’ and ‘Velocity’ components, would the Movement system itself maintain the data represented by the Position and Velocity components?

If so (and I believe that’s what you’re suggesting – if not please correct me) – how do other systems consume this data? For example, suppose that I also have a ‘Rendering’ system that uses the Position data to render the entity to the screen. How does the Rendering system get access to the Movement system’s data?

Is this data copied between systems, such that both Movement and Rendering have arrays containing the same Position data? Or is one system designated as the canonical source for Position data that other systems must pull from? Or would Position updates be broadcast via messaging from the Movement system, which the Rendering system subscribes to in order to update the Position data?

1. Randy Gaul Post author

If you want to have high performance you’ll likely carry redundant data. Memory fetches from RAM on PC hardware is just so slow compared to having things sit in the CPU cache. While physics is simulating it will operate on a local cache of any information it needs, and once processed a synchronization with data elsewhere can occur. This prevents wasteful memory fetching within inner systems and loops, and focuses more on batch processing and array transformations.

However in a practical sense, usually graphics and physics systems will be quite isolated from any component architecture. Within these systems there is undoubtedly some implementation of data oriented design, otherwise the systems would be awfully slow. So in this way I would actually recommend have fewer, but less specialized components. Physics and graphics components will probably just simple interfaces to whatever graphics or physics implementation is occurring underneath. The smaller and more specialized components become the more the entire engine has to obey a single paradigm in order to match the component format.

So what this means for many users of middleware is that a component based architecture will really only help a lot with flexibility in terms of creating new game objects, or modifying old ones. Using a component architecture to try to maximize performance and simplify code will probably just be an annoying headache without much of a cause. Using data oriented design within specialized systems that require high performance is where performance considerations is really helpful.

17. Alexander Liarokapis

This is an incredible article Randy.

Same as you I’ve tried to implement a naive ECS framework. I really liked the decoupling that it offered and implementing new features was incredibly fast. Unfortunately I didn’t take data locality into account when writing it and as a result the engine couldn’t handle more than a few tens of thousands of objects.

When writing the framework I concentrated a lot on allowing for fast implementation of features. It was intended to be used by others as well, so I didn’t want to deal with any enum bookkeeping when making a new component or system.

In the end I settled with Component being an empty class to allow components to be grouped together. Systems are also derived from a System class. When making an entity you pass a pointer to the main Engine class. That class owns the systems and updates them accordingly when you add/remove a component to an entity.

According to a registration_condition that you define for the systems, they then store the entity to an entity vector. A PhysicsSystem for example may be implemented like this:

Likewise a component may be implemented like this:

Now, if I am to store the different components in the appropriate arrays, how would an entity update it’s indexes for the different system types and how would they be used from the user without them having to access the entity class and maintain an enum?

1. Randy Gaul Post author

Hi Alexander! Glad you liked the article. Short answer: you can use a handle translation to allow your arrays to be moveable at run-time. If you don’t want to use an enum to refer to different handles you’ll have to use some sort of other type of translation.

More details: An enum is nice because an array index is super fast. You can possibly use a linear or binary search to grab an index if you don’t want to have compile-time enumerations. The problem with not using an enumeration and pre-spacing an array is you don’t know where in memory the reference to a particular component will be. In my own open source engine I solved this problem by making a distinction between Lua components and core components. A core component would be something implemented on a lower level and be accessed by an enumeration index. A Lua component would be much more flexible. New types can be made at run-time and added/removed/modified freely. These are retrieved by converting the Lua component name by string to an enumeration index. I also have a run-time enumeration editor that modifies C++ code and allows new Lua components/enums to be created/modified/removed during run-time. This lets high flexibility and lower performance, or low flexibility and higher performance components be chosen between as a judgement call. There isn’t going to a one-sized package that fits all.

The same goes for any complex internal system that requires high performance. My anecdotal recommendation (without a full article) is to write broad components, instead of find grained components. Perhaps a 3D Model for rendering, or a Rigid Body component would suffice. Both of these components would have quite a bit of data and initialization code along with it, but trying to break fundamental ideas (model and rigid body) like these forces the component/aggregation model into other areas of code that might not be suited for such an implementation.

Let graphics be graphics, let physics be physics, and use components where they really matter. Components are great for piecing together functionality to define something new. This sounds like gameplay and game designer friendly code! Often times a “physics component” will be best implemented as a light (and as efficient as needed) wrapper for whatever underlying physics technology is running.

18. Alexander Liarokapis

Thanks for the informative reply Randy, I also enjoyed your new post.

I want to let you know that I finished adjusting my framework to work with Component Containers (vectors) however I am not sure if this approach is cache friendly.

Basically, each Entity now has handles that are indexes to the containers (or -1 denoting that they don’t have the appropriate component).

The systems hold a list of the entities with the correct components, and use a Mapper to access the components using the entity’s handles. This is what the Mapper class looks like:

 template class Mapper { public: Mapper() : m_index(engine.getIndex()), m_container(engine.getContainer()) {} T& get(Entity* entity) { return m_container[entity->getHandles()[m_index]]; } private: size_t m_index; Container& m_container; }; 

and this is how it may be used in a system:

 class RenderSystem : public vf::System { public: RenderSystem(sf::RenderWindow& window) : window(window) {} bool registration_condition(vf::Entity* entity) const { return entity->hasComponent() && entity->hasComponent(); } void update(float dt = 0) { vf::Mapper mgraphics; vf::Mapper mphysics;

 

 window.clear(); for (auto& entity : entities) { auto& sprite = mgraphics.get(entity).sprite; auto& physics = mphysics.get(entity); sprite.setOrigin(16,16); sprite.setPosition(physics.position.x, physics.position.y); sprite.setRotation(physics.rotation); window.draw(sprite); } window.display(); } private: sf::RenderWindow& window; }; 

Sorry for the amount of code by the way, I am not an expert in caching and I would like to know if this is a naive implementation or if it’s more or less what you mean.

19. mateus

Hi, thank you so much for this article.I was wondering if you ever worked with Unity, and if so, i would like to ask you, if  you have any idea of what happens inside the hood when you add a component(script) to an GameObject.I ask this, because it seems that Unity creates a new object that inherits from the component, in that sense, is unity a component based engine, a plain OO engine or a mixture of both? Again , thank for this great article.

20. Robin Hübner

I love this article, I was already thinking about various implementations of entity component systems, having implemented some naive ones which were all incredibly cache-inefficient, mostly just treating the GameObject itself as the component container, the components referencing eachother and calling methods directly.

After reading your article, the idea of having “managers” for a certain type of components, you can have the top level manager handle componentmanagers, which in turn hold the components in contigous memory. You could probably even accomplish the same sort of placeholder components by swapping out component managers, things like having AISteeringComponent and PlayerSteeringComponent and so on.

Currently working on a sort of robocode-like game written in D which communicates over WebSocket with the browser, the browser acting as a “view” to the server, intended to make it easier for people to get into the programming and competing.

Very inspirational!

21. sebastiaan

Hello there:)

I recently stumbled upon your articles and I have to say they are amazing

I started only learning c++ recently so I have a few problems with trying to implement this design. how do would you add a component to an object, and where would you store the components?

sorry if these questions are really silly.

a fellow Teamliquid member.

1. Randy Gaul Post author

There are a lot of answers to this question, and they vary in strengths/weaknesses, as well as difficulty of implementation. If you like you can email me with specific questions (email in my resume on this site). Briefly, my personal preference is to store components in arrays, and arrays are allocated one at a time as necessary (like pages in a paged allocator, or like a batch). Components relate to one another through an identifier (an integer where different bits represent different things), so there’s no “entity object” in memory, as the entity is conceptually just components that makeup the entity.

22. tuket

Great article!

I have still one dubt. Each handle is an index to one array. So if you delete one element from that array you will have to shift the elements to fill that space. That would make the handles that refered to those elements invalid. Do I have to update all the handles that refered to those elements? Do I need to traverse all the objects in search of handles to components that have became invalid each time I delete an object? That seems like a lot of work.

Thanks.

1. Randy Gaul Post author

Usually people just swap the last element of the array into the empty spot, so only one handle needs be updated.

23. Vanja Djurdjevic

Hi Randy!

I liked you approach very much and have started something on my own using similar concepts you presented here. However, one question boggled me and that is why I am writing this:

How would you, for example, manage fixed tiled movement of game objects (this includes collision between objects and lets say a pass map matrix)? Would you use a centralized game engine system, like Physics or GameLogic?

Thanks in forward

Vanja Djurdjevic

1. Randy Gaul Post author

I would have some code that holds tile data and colliders. This code would be completely independent of any components or systems or engine. Usually specialized pieces of code really should only care about the specific task they need to solve. So, if you need to collide shapes against tiles, write code that does only that, and really well.

Then you can write small components that “wrap” around these specialized systems as needed. When using this approach you don’t usually end up with “granular” components. Instead you get some wrapper components that interface with lower level systems, and do a more broad range of tasks.

Granular components are much more interesting and useful for gameplay specific code, not the lower level specialized code.

24. Johan Vikstrom

Hi! I want to create a basic gameengine for learning purposes (obviously :P)

Now I have a problem, when I create an ObjectFactory I get a circular dependency between GameObject and the ObjectFactory which I assume is the reason it doesn’t compile.

Here’s the ObjectFactory source :

It gives me an error on line 11, that “GameObject hasn’t been declared”.  (When I comment out line 11 I can compile, but that’s not really an option as I see it)

And GameObject:

I don’t really see any other way to do this other than creating one ObjectFactory and ComponentFactory.

Oh and also,  I haven’t created the function for addGameObject in ObjectFactory as I’m getting an error which prevents me from compiling.

Oh and also #2, I’m very open to critizism :)

1. Randy Gaul Post author

Try using a forward declaration of both GameObject and Component from Factory.h. This way you can have forward declared types for your pointer return/param types.

25. chris

Hi I have been implementing my own version of this. Currently I have a renderer which holds an array of components called renderables. Renderables contain a material and a mesh. The renderer loops through all these renderables and gives them things like the perspective and view matrices needed to render. My game objects are made up of a transform and an array of handles that correspond to the component in the renderable array. All these things are generic to almost every object that can be rendered. My issue comes when I want aspecialized object say a clickable sprite they will change color or something. My renderables are in an array which makes it impossible to have polymorphic functionality and thus not able to send the necessary data from the game object to the renderable and thus to the material. How do I get specialized behavior in this architecture.

1. Randy Gaul Post author

I’d avoid trying to write super generic code. The reason to use some kind of component system is not to make generic solutions or architectures, it’s to allow the ease of creating a variety of specific systems to interact with one another. There’s a saying, the more general something becomes the less powerful it becomes.

You could have another array to hold data for non-moving sprites, and a specific system to deal with this kind of data. You could also keep all kinds of renderables in the same array, even your 2D sprites, and then just sort the array whenever needed. This way you can loop over the array without branches. Or, you could skip the sorting and run a system on the array that branches depending on what kind of data is present (similar to polymorphic functionality). There are even more options than these. It all depends on what you want to do and what tradeoffs you want to make.

26. MS

Hi!

I was wondering about a couple of things when it comes to ECS:

When you have you arrray of handles stored in an entity, and want to find a certain component, say GraphicsComponent, how would you do this with only using an integer? How can I know that for example 2 equals GraphicsComponent? Do you just #define GRAPHICSCOMPONENT 2 somewhere and use that or is there a better approach to this?
In my GraphicsSystem, I have an array where all GraphicsComponents are stored. However, I need the data from my TransformComponent to know where to render the data in GraphicsComponent. Should I also store an array of TransformComponents in the GraphicsSystem? Should I get the handle to the entity from the GraphicsComponent and get the TransformComponent from the entity or would the better approach be to use some form of messaging system to get data from other components? If that is the case, how can you do this?

Also, in the part about Messaging, I noticed this code:

Where and how would you define say, ePlayerNearby and eActivate? Would they be some kind of constants stored somewhere?

27. Chris

Instead of making Glimmer an action on the treasure chest and part of the entity system, it could be moved into the “View” and made purely visual as part of the rendering.

1. Randy Gaul Post author

That’s true, but then there is also the lost “area of influence” effect that can be nice to have.

28. James

Hello,

Great article. One question I have though is how do you avoid a dynamic_cast in your Component* GetComponent(int id) call? If you store your components on an entity by their base class (i.e. std::vector<Component *> m_components;) then it seems like a (slow and distasteful) dynamic cast would be required in order to get a derived component off an entity? Or do you do a dynamic_cast? For example, TransformComponent *transform = dynamic_cast<TransformComponent*>GetComponent(23);

Thanks, James

1. Randy Gaul Post author

Two options: first is to use a reinterpret cast and make sure your code has no bugs. The second option is to store (for example an enum) that defines the type of the component in the base class. Then create a Cast() helper function that works kinda like: Transform* t = Cast(c, CT::Transform), where CT is an enum standing for Component Types. Inside the cast helper you can do a quick if else statement, returning null (and possibly spewing some debug information) upon a type mis-match.