entity system implementation

Started by
23 comments, last by dendrite 8 years, 3 months ago
Apologies in advance for the lack of line breaks; it appears when i type it in but somehow gets removed when i submit, and i'm not sure how to fix. I'm pretty new to entity systems, and these questions arose while trying to implement one for a game. 1. There seems to be 2 ways of implementation: a) to have each component in different arrays, and have each entity be associated with the indices of the components attached to it. b) to have the entity object itself store a list of its components. Aside from better cache friendliness and less overhead from virtual functions, why does the first approach seem to be more popular? B seems a lot easier to implement, and functionally, it seems you get the same separation of data and behaviour. 2. A query that I'm making often is "which entities have the following components in them?" and "which entities have the following components, as well as not having some other set of components?". I'm currently using a naive check over all components of the entity to implement these queries. Is there a better way?
Advertisement

I had the same problem.

I decided to take the memory hit and set a MAX_ENTITIES that my engine can support and block out arrays for MAX_ENTITIES for each component. This way each entity is basically a column in the table and doing checks for "does my entity have X component" is just a case of checking the component at the same index as the entity. Ofcourse you will have unused slots in the array but you are also never left wanting as at any point its possible to turn on a new component for an entity by enabling a component at a given index without the cost of an allocation etc. I believe it is also popular to have a bitfield in the entity to discern which components are enabled for it.

Each subsystem iterates over the components checking components[x]->IsEnabled() before processing them.

I believe I responded in your other post, but I'm not sure I agree "the first approach seem to be more popular" and I don't think you should really concern your self over forcing all components of the same type to be stored in cache friendly location. Do what you feel is best for you, especially since you're new to the paradigm.

I can promise you, as a single developer, I doubt you'll be writing code that required the savings you'll get from grouping all components together.

And, FWIW, the "MAX_ENTITY" value can be really bad if you can have thousands of entities in a game; the harm may out weigh the benefits. If you're in the hundreds, maybe it's OK, but it's still not the way I'd do it.

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)

Have you tried the MAX_ENTITIES before BeerNutts, i'm curious what harm comes of it in your experience?

And, FWIW, the "MAX_ENTITY" value can be really bad if you can have thousands of entities in a game; the harm may out weigh the benefits. If you're in the hundreds, maybe it's OK, but it's still not the way I'd do it.


While it's not the way I'd implement it either, what harm are you referring to? It's a known constant memory cost, with known limitations.
I'd consider it (or the use of vectors) as the most simple and straitforward way of doing it, with more complex ways available if you have more intricate needs.
(for example, the way described above is fast, but there's potentially an even faster way)

And, FWIW, the "MAX_ENTITY" value can be really bad if you can have thousands of entities in a game; the harm may out weigh the benefits. If you're in the hundreds, maybe it's OK, but it's still not the way I'd do it.


While it's not the way I'd implement it either, what harm are you referring to? It's a known constant memory cost, with known limitations.
I'd consider it (or the use of vectors) as the most simple and straitforward way of doing it, with more complex ways available if you have more intricate needs.
(for example, the way described above is fast, but there's potentially an even faster way)

For every possible Component type, you need to make an array of MAX_ENTITIES large, and, if that's thousands of entities and 10's of components, you've wasted a lot of memory. I suppose memory isn't such a burden any more, but it just seems like a waste.

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)

Sure, I declared that issue up front. I'm yet to find a balance between minimal memory consumption and 'very fast' lookup of components that doesnt involve storing the components on the entity.

A reasonable compromise is to store a set of 1-bit flags on each entity, which tells you which components are attached to this entity. If you need to retrieve the component you'll still need to search for it in the relevant component array, but at least testing for it's presence is now cheap.

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

A reasonable compromise is to store a set of 1-bit flags on each entity, which tells you which components are attached to this entity. If you need to retrieve the component you'll still need to search for it in the relevant component array, but at least testing for it's presence is now cheap.

Sure that would work. I can't think of any occurrences where i've wanted to see if it has a specific component without actually wanting to do something with it though, not personally.

EDIT: I just did a quick google search and found this article again http://bitsquid.blogspot.co.uk/2014/09/building-data-oriented-entity-system.html. Under the heading 'accessing data' it talks about having a much smaller table of indices that provide an indirection to the components at their respective indices. So it looks like you'd use:

MAX_ENTITIES * sizeof(int) * MAX_COMPONENT_TYPES bytes for the indirection table and then a trimmed down component table.

rather than:

MAX_ENTITIES * MAX_COMPONENT_TYPES * AVERAGE_COMPONENT_SIZE and no indirection table (as I currently have).

So you'd save a tonne of memory that way.

I use a separate table of indices (one row for each entity) that have an index into the component arrays. So something like:

// Given an entityIndex and a 0-based componentId,

int componentIndex = componentIndicies[entityIndex * MaxEntityTypes + componentId];

if (componentIndex == -1)

{

return nullptr

}

else

{

return &componentMapper[componentIndex]

}

This topic is closed to new replies.

Advertisement