Jump to content
  • Advertisement
Sign in to follow this  
inzombiak

Component-based architecture - entity and component storage

This topic is 1358 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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?

Share this post


Link to post
Share on other sites
Advertisement

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.

Share this post


Link to post
Share on other sites


[...]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 ;))

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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".
 

Edited by inzombiak

Share this post


Link to post
Share on other sites

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.

Edited by inzombiak

Share this post


Link to post
Share on other sites

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.

 

Share this post


Link to post
Share on other sites

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

Edited by inzombiak

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!