Component-based architecture - entity and component storage

Started by
12 comments, last by Irlan Robson 9 years, 1 month ago

Hi all,

I recently decided to move my game from an inheritance based architecture to entity-component based one. I have the whole Component system set up, but I'm having problems figuring out how to store and pass them around. Below is a bad image of my architecture.

[attachment=26133:Game Architecture.png]

Right now the operations are as follow:

The Game class passes information and objects between classes as well as contains the mainloop

The LevelLoader class reads the tile info from a .tmx(TIled) file and generates the tile Entities, storing them in one of three vectors based on type: foreground, background and collision box. I separated them to make rendering and collision simpler. After loading is complete ALL the Entities are transferred to the GameObjectManager class.

Every frame after this is processed as follows, the GameObjectManager updates all its entities, which update their components, then Game extracts the entities vector from GameObjectManager and hands either the vector or elements of the vector individually to the different systems.

The Systems handle their operations and this cycle repeats.

This is where I feel like I'm making a mistake. I have the entities and I have the component, I just don't know how to give the different systems (Physics,Renderer Input etc.) access to them. Currently I just get the std::vector<Entity> container from the GameObjectManager class and pass it into each system, but it just doesn't feel right. Objects that have no physics component have to be iterated over in the Physics system and ones that are just empty collision boxes get passed to the Renderer.

One idea that came to mind was having a vector of pointers for each type of component and passing the corresponding vector to the corresponding system. This would certainly help the game run smoother, but I think adding new component types would become more difficult.

Another is to sift through the vector of entities in the Game class and just pass the entities components to the right system:


for (int i = 0; i < entity.size(); ++i)
{
	if (entity[i].hasComponent("phsyics"))
	{
		physicsSystem.Update(entity.getPhysicsComponent());
	}
	if (entity[i].hasComponent("render"))
	{
		renderSystem.Update(entity.getRenderComponent());
	}
....

}

With all this said, my question is, what is the most efficient way of handling entity/component storage and accessing. Should I throw them all in a single container and just pass it around and let the systems sift through? Or should I manually sort the components beforehand and pass the systems only what they need? Is there a better/smarter way of handling this?

Advertisement

No idea what exactly is going on there but what you have done isn't a component thing to me.

Just because you can put arbitrary "component" object handles inside an array, which allows you to build "entities" does not mean you are component based.

The above is not component based either, it's switching behaviors exactly like a monolithic entity would do. I'll agree that has some very slight flexibility added.

No idea what a "physics" component is supposed to be either. I assume it is a rigid body representation.

Here is ECS, condensed to the its core.

There are no entities. There are only the components.

See Fig-2.gif

(http://cowboyprogramming.com/2007/01/05/evolve-your-heirachy/)

The message "between the lines" and showcased in the above diagram is: the execution/update of components is independent from other types and can be - in theory - completely asynchronous. I dare everyone in writing a fully async, fully ECS-only system but that's for another time.

So, what does that mean? It means basically the opposite of this:

One idea that came to mind was having a vector of pointers for each type of component and passing the corresponding vector to the corresponding system.

You should really have the components exist in the systems only and link to them on need rather than keep them floating around and putting them back in on need. Seriously, where do you think rigid bodies are going to go each frame? In the physics library. Where do you think the models will go if not in the rendering subsystem? No point really in taking them out: you take out reference / pointers to them and leave them live in their own land using a base class or a proxy of some sort. Internally the subsystem accesses everything it needs while externally you don't.

Previously "Krohm"

As you may be aware, there are a large number of different implementations of component based systems.

Especially in languages such as C++, the benefits of ECS designs can be the ability to employ contiguous memory. If you have each system allocate a pool of components, then you can reduce the frequency of cache misses, and hence improve performance of system updates.

Hence, when you register a component with an entity, it makes sense to request it from a system, which will maintain an internal pool (and therefore update internally) of components.


IComponent* physics_component = physics_system->create_component();
entity->components.push_back(physics_component);

// Some time later
double delta_time = 1.0/60;
physics_system->update(delta_time);

This has its difficulties when you have systems which share components with other systems. Generally speaking, avoiding this dependency helps a great deal.


[...]The LevelLoader class reads the tile info from a .tmx(TIled) file and generates the tile Entities, storing them in one of three vectors based on type: foreground, background and collision box.[...]

Thing to remember is that ECS is for game objects. I'm not sure whether you consider here to wrap everything into an entity. That is not necessarily a god idea.


Another is to sift through the vector of entities in the Game class and just pass the entities components to the right system:
Code here

That approach is definitely not what you want, because that code snippet processes each entity individually from input down to rendering in one go. That is almost ever wrong. Instead you want to want let all interested entities be input processed, then let all interested entities ..., then let all interested entities be rendered. (In the meanwhile Krohm has posted an image that shows what I mean ;))

Just because you can put arbitrary "component" object handles inside an array, which allows you to build "entities" does not mean you are component based.


Then you have a really weird definition of a component. His game objects are very clearly composed and not monolithic. That's all using components means, in any context; ECS is _hardly_ the first place the word "component" has ever been used in computer science or even game development. smile.png

The OP's architecture isn't particularly efficient, no; I'd go so far as to say it's actually the least efficient component system I've seen yet for a game engine, though it's not unlike some of the component systems you might find in certain Web or UI frameworks. Simply looping over every component and calling a virtual Update method on it would likely be more efficient... and is good enough to ship a commercial AAA game with.

Sean Middleditch – Game Systems Engineer – Join my team!

As you may be aware, there are a large number of different implementations of component based systems.

Especially in languages such as C++, the benefits of ECS designs can be the ability to employ contiguous memory. If you have each system allocate a pool of components, then you can reduce the frequency of cache misses, and hence improve performance of system updates.

Hence, when you register a component with an entity, it makes sense to request it from a system, which will maintain an internal pool (and therefore update internally) of components.


IComponent* physics_component = physics_system->create_component();
entity->components.push_back(physics_component);

// Some time later
double delta_time = 1.0/60;
physics_system->update(delta_time);

This has its difficulties when you have systems which share components with other systems. Generally speaking, avoiding this dependency helps a great deal.

This makes all of the sense. Thank you. I had been following the "Game Coding Complete 4" book, but I couldn't find where the actual components are created, so I thought "just toss em on the heap".

I would separate low-level systems and high-level systems:

14twt45.jpg

My current issue was(is) with passing the information within the components. I'm not sure how this separation of systems would help.

I'm currently trying out Krohm's/Angus's solution. Its not as clean as having everything come out of a factory, but I can see how it would be better of the performance side.

As a side note, if physics is your stuff, play with some physics API first!

Then you have a really weird definition of a component. His game objects are very clearly composed and not monolithic. That's all using components means, in any context; ECS is _hardly_ the first place the word "component" has ever been used in computer science or even game development.

Well, you got me there. I should have been more explicit in intending the word component in this case is to be intended uniquely as intended in CES.

Previously "Krohm"

It was just a general system I added for the sake of explaining my situation, but will do.

This topic is closed to new replies.

Advertisement