Object-oriented – Entity Component System Coupling

class-designdesignentityentity-component-systemobject-oriented

Lately I've been working on a small personal project which is basically an Entity Component System framework with autoupdated Systems.

While I have a pretty good idea on the way the framework should work, because of lack of experience I am having trouble with actually keeping everything decoupled.

Some details on the framework:

Each entity is defined by it's components.

Systems are responsible for the actually modifying the entities by changing their components.

In order to improve locality of reference, instead of keeping each component in the appropriate entity,
all components are stored in homogenous vectors and each entity keeps a list of indices to each vector.

Since each System modifies specific components, it should keep a list only of the entities with the corresponding components.

How I dealt with all of this until now was to have a ComponentManager, an EntityManager and a SystemManager. These classes however have very tight coupling with each other. The EntitManager needs to have access to the ComponentManager in order to handle the size of the the index lists and the mapping of each component type to them. It also needs access to actually add the components in the appropriate vector.
Another coupling is between the EntityManager and the SystemManager. Whenever an entity is created, it needs to be added to the list of the appropriate Systems.

A general event bus would appear to help but I am not sure how to implement it without making it global.

How do I improve this design by removing coupling while still maintaining the system's functionality?

Best Answer

How do I improve this design by removing coupling while still maintaining the system's functionality?

You don't go much into your functionality, so I'm going to make some guesses and go over the general approaches:

  • System -> Component - you say that the System only works with specific components (say, a physics system changing velocities), then why does the system care about entities at all? The system should be free to work with the components in relative isolation.
  • Entity -> Component - you mention that there's some manner of index lists between the entity and its component. This strikes me as odd. Entities should have references to their components (or vice versa) - even if that's as thin as a foreign key. By using indexes, you're exposing an implementation detail from the ComponentManager that is harming your coupling.
  • Entity -> System - again, if you have systems work with components, then there should be no tie here. An entity is created, which knows which components to make (or vice versa, the components are built and then aggregated/dependency resolved by the entity) - regardless of the system manipulating them.

Personally, the design I've seen work well is having the entity be a very, very thin layer that aggregates the components, acting as a context so that the components can play nice with one another. The outside world can then query and act on the components' public interface.