I have an Entity class and a Component class. The Entity class has a list of attached components, and each component also has a member variable that is a reference to the entity that it is attached to (cyclical design).
Then, there is the EntityManager class, which has a list of (you guessed it!) entities, and each entity also has a reference to its encapsulating entity manager.
The reason for this cyclical design is due to data reliance. To explain further, my Entity class is essentially just a giant bucket of data: any data any type of entity needs already exists on this class when it is instantiated. However, in order to make use of this data, the Entity needs the relevant components attached. For example, my Rendering component takes the Entity's spriteData member and draws it to the backbuffer. Without a rendering component, spriteData is not utilized. Since my components need to access the Entity's member variables, each component needs a reference to the Entity it is attached to.
For an example of why my entity needs a reference to the entity manager, it is because some components (such as collision) need to access other entities' data buckets in order to function (for collision, this would be checking nearby entities' position vector and comparing it to the component's referenced entity).
There is more to it than this, but I just wanted to highlight the central idea of what I was doing, and wanted opinions on whether a cyclical approach like this (with little data encapsulation as well..) is a good idea or not. Maybe I'm just overthinking it /shrug. Opinions on how to steer the design would be hugely appreciated, as well.
Answer
Entity systems do exist since years, your design decision is not new. For example take a look at the Artemis framework, or my own implementation.
To provide some feedback on your system, I wrap it the other way around. Your current approach is to have an entity class and attach properties to it.
class Property
{
};
class Entity
{
std::vector properties;
};
std::vector entities;
Instead, you could drop the entity base class, represent entities by integer ids, and group the properties of the same type together in maps.
std::unordered_map sprites;
std::unordered_map positions;
Which sprite corresponds to which position is given by the id thus the integer key. The advantage of this design is that it leads to more data oriented code. It is much faster, to loop over all PositionProperties
and update them (which could even be done in parallel), than to loop over all entities and each update all their different properties.
Using ids to represent entities also has the advantage that you could easily store them to disk and load them back into the system without loosing their identity.
No comments:
Post a Comment