Question about the Entity Component System architecture

Started by
6 comments, last by Kylotan 10 years, 11 months ago
Hey everyone,

I've been reading up on the Entity Component System paradigm ( http://www.gamedev.net/topic/643095-good-articles-on-entity-components-systems/ has been very helpful) and I think I understand everything I need to implement it except for one thing:

Where do the components "live"? Getting into implementation specifics, I'll be writing this in C++. So, for the sake of example, let's say I have a position component, a velocity/movement component, and a motion system which acts on both components.

Would it make sense for each entity to have a data member container consisting of pointers to components? If so, how would the motion system keep track of which entities have position and velocity/movement components? Or maybe a better way of phrasing the question is: How does the motion system keep track of which components it needs to iterate over when it runs?

When I look at diagrams and read articles about ECS, everything seems to make sense to me. But when I sit down with a pen and paper and try to map out the class relationships, my level of understanding starts to break down.

Thanks!

Edit: I've thought about this a little bit more, and maybe the a good approach would be to have each system contain a container of pointers to entities that contain a matching set of components. This would mean that every time an entity adds or removes a component, it would have to be examined by each system to determine if it contains the right components to be used by that system. However, this also means that each system doesn't have to go through and check EVERY entity to see if it has the right components in every iteration of the game loop. Thoughts? Am I heading down the wrong path?
Advertisement

There are hundreds of previous posts on matters like this. Have you used the search function? (The short answer is - different people do it different ways, and they all work.)

The short answer is - different people do it different ways, and they all work

^this.
"ECS" is not as specific as other design patterns. It's a very vague description for hundreds of different designs, with the only common pattern being "components are some kind of structure, entities are groupings of components". That detail alone can be implemented in dozens of ways, and there's dozens of other details that may or may not even exist depending on the overall design, and whether the designer has come from a relational, OO, procedural or functional background, etc...

Different "ECS" systems are also designed around different requirements.
Sometimes the whole point is so that different components can automatically find each other, and send messages to each other without the programmer having to manually bind them (the "entity" is basically a message router and service provider).
Other times the whole point is just to allow entity "templates" to be defined in data (the component connections might be specified in the data files or magic like above), with the ECS basically being a fancy serialization and inversion-of-control library.
Other times the whole point is to decouple different parts of entities so that data can be rearranged into cache-friendly structures and processing can easily be multi-threaded (i.e. a design stemming from performance considerations, to avoid the pitfalls of OOP).

Given this huge range of designs falling under the "ECS" banner, you really have to be able to define what it is that you want your ECS library to achieve and what it's requirements are, before you can evaluate the merits of different design choices.

With that out of the way...

Where do the components "live"? Getting into implementation specifics, I'll be writing this in C++. So, for the sake of example, let's say I have a position component, a velocity/movement component, and a motion system which acts on both components.

Would it make sense for each entity to have a data member container consisting of pointers to components? If so, how would the motion system keep track of which entities have position and velocity/movement components? Or maybe a better way of phrasing the question is: How does the motion system keep track of which components it needs to iterate over when it runs?

I'm not a fan of the automatic binding (entity as message router and service provider) style of ECS, and I personally prefer a style where entity is a component, rather than some first class concept of the pattern. So, I'd KISS and just implement this in 7 lines of code, with the supporting library only being a compacting-pool class (a pool that moves items to always be contiguous, whenever a 'hole' is created through erasing an item) that supports handles (because pointers won't work due to the compaction):


struct Position { Vec3 pos; };
struct Movement { Handle<Position> who; Vec3 velocity; };
void MovementSystemUpdate( const Pool<Movement>& movements, Pool<Position>& positions, float dt )
{
  for( const Movement* m=movements.begin(), *end=movements.end(); m != end; ++m )
    positions[m->who].pos += m->velocity * dt;
}

Bam! "ECS" without the bloat cool.png

FWIW, here what i think are the 2 most used options for where the components live, and how they are coupled with entities:

#1, Components simply have an "int EntityOwner" that stores which entity owns them, and entities are simply an unique number.

#2, Entities contain a list of pointers to Component it owns. (something like a std::vector<TComponents> Components member).

How they are accessed is a much larger answer that has been covered.

My Gamedev Journal: 2D Game Making, the Easy Way

---(Old Blog, still has good info): 2dGameMaking
-----
"No one ever posts on that message board; it's too crowded." - Yoga Berra (sorta)

In my ECS, which is somewhat based off the artemis framework, the components are stored in arrays in the "entity manager". The entity manager also maintains a mapping from entity to indices into these arrays (so that's how we determine which components are associated with a particular entity).

Each system declaratively states which types of components its interested in (e.g. "I require the Aspect and Position components"). Whenever an entity aquires Aspect and Position, the entity's index is automatically added to a list in that system. So each system is always guaranteed to have an up-to-date list of the entities (or rather, indices to the entities) in which it is interested.

In my ECS, which is somewhat based off the artemis framework, the components are stored in arrays in the "entity manager". The entity manager also maintains a mapping from entity to indices into these arrays (so that's how we determine which components are associated with a particular entity).

yes, relational database type thing. this seems the way to go.

i was thinking an array for each component type, and its associated methods, and a list (array) of entities, of course with indices pointing to the other databases.

your method is exactly the way i'd do it myself.

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php

Thanks for all the help/feedback. You guys have given me a lot to think about and consider when designing this.

As far as Hodgman's point that there are different reasons to pursue ECS, I'd have to admit that my reason seems more basic than any of the ones he listed. It simply seems like a nice, clean alternative to rigid inheritiance heirarchies or potentially problematic multiple inheritance situations. Does this seem like a strong enough justification for the system in and of itself?

Also, in light of this fairly general goal, what are the pros and cons of storing the components within entities as opposed to in containers or structures that exist outside of the entities?

I'll keep hackin away and update this thread if more questions surface.

It's a common requirement in software to be able to have an object that can vary its behaviour in several different ways, so that different instances of the same object can behave differently. Much of the book 'Design Patterns' talks about ways you can achieve this, eg. with the State pattern, the Strategy pattern, Composite pattern, Decorator pattern, etc. It's a false assumption to believe that the only practical way to get similar-but-different objects in an OOP application is to employ large inheritance structures or multiple inheritance approaches. As such there is nothing new about this particular problem and no intrinsic reason why anybody should feel that a formal component-based-entity approach is the one true way forward.

I like to have a single Entity class and then I vary the behaviour within the entity by swapping out subcomponents as necessary. But I don't make everything into components, only the bits that I think need to be interchangeable, and which don't lend themselves to any simpler approach. (eg. Sometimes a simple if (npc) check will do, meaning there's no need to create separate PlayerCharacter and NonPlayerCharacter components.)

If you don't have a reason to factor out components into a separate structure, don't do so. You'll only waste a lot of time and energy finding ways to communicate between the components effectively. Probably the best reasons to have an 'outboard' architecture like that are for increased parallelism and to benefit from cache coherence, neither of which should be a concern to you at this point. My opinion would be to just store the components within the entity and allow them to access each other if necessary.

This topic is closed to new replies.

Advertisement