8
\$\begingroup\$

Architecture description

I'm creating (designing) an entity system and I ran into many problems. I'm trying to keep it Data-Oriented and efficient as much as possible. My components are POD structures (array of bytes to be precise) allocated in homogeneous pools. Each pool has a ComponentDescriptor - it just contains component name, field types and field names.

Entity is just a pointer to array of components (where address acts like an entity ID). EntityPrototype contains entity name and array of component names. Finally Subsystem (System or Processor) which works on component pools.

Actual problem

The problem is that some components dependents on others (Model, Sprite, PhysicalBody, Animation depends on Transform component) which makes a lot of problems when it comes to processing them.

For example, lets define some entities using [S]prite, [P]hysicalBody and [H]ealth:
Tank:   Transform, Sprite, PhysicalBody
BgTree: Transform, Sprite
House:  Transform, Sprite, Health

and create 4 Tanks, 5 BgTrees and 2 Houses and my pools will look like:

TTTTTTTTTTT // Transform pool
SSSSSSSSSSS // Sprite pool
PPPP        // PhysicalBody pool
HH          // Health component

There is no way to process them using indices. I spend 3 days working on it and I still don't have any ideas. In previous designs TransformComponent was bound to the entity - but it wasn't a good idea. Can you give me some advices how to process them? Or maybe I should change the overall design? Maybe I should create pools of entites (pools of component pools) - but I guess it will be a nightmare for CPU caches.

Thanks

\$\endgroup\$
1
  • \$\begingroup\$ Multiplayer? (It's relevant) \$\endgroup\$ Feb 18, 2012 at 10:38

1 Answer 1

2
\$\begingroup\$

Disclaimer: Purely going off of my systems class knowledge.

I originally thought, why not just use a hash function on entity ID for your index?

That way you'd get

T[A]nk:   Transform, Sprite, PhysicalBody
B[G]Tree: Transform, Sprite
H[O]use:  Transform, Sprite, Health

and create 4 Tanks, 5 BgTrees and 2 Houses and my pools will look like:

OGAGAGGOGGG // Entity pool (letters corresopnding to entity type)
TTTTTTTTTTT // Transform pool
SSSSSSSSSSS // Sprite pool
P P P  P    // PhysicalBody pool
H      H    // Health component

Or however it was the entities happened to be placed. You can have pools for all of the components and for entities and use the entity pool as the "master," such that collisions are checked against the entity array. But of course you get the problem of recycling components and entities.

If your game design allows it, you could plan ahead where each type of entity goes so you could get the most efficient packing possible. Say entities 0-20 are reserved for tanks, entities 21-30 for houses, and 31-60 for BGTrees. You might not be able to efficiently spawn infinite baddos, and kinda defeats the dynamism of component systems, but it would solve the problem. I don't see a way to have your cake and eat it too.

I was thinking about ways to maybe speed up the render pass where you have a RenderingComponent that contains all the data that the rendering system needs so it's able to just blow through an array of these things, but then there's overhead of copying data. Also, any time you dereference a pointer you're thinking about whether or not it's still in the cache.

If you want a super speedy game, I'd say plan your allocation out. If you want a flexible game architecture, roll out the hashtables and string IDs. Any time you want flexibility you need to build abstraction, and therefore will incur overhead.

TL;DR;
Based on what you described, I would create a higher level RenderComponent with pointers to Sprite and Transform components and give it the necessary references when you initialize the entity.

(Apologies for any perceived rambling, I've been thinking about this in my system as well, so this was an opportunity to think through it)

\$\endgroup\$
4
  • \$\begingroup\$ I don't know if hash maps are so effective. I want to have an entity systems where subsystems contains DOD functions like: void update(u32 n, PhysicalBodyComponents* bodys, Transform* transforms) I want to work on many inputs and to split this function on multiple cores. It is possible with hashmaps? \$\endgroup\$
    – mani3xis
    Jan 18, 2012 at 8:28
  • \$\begingroup\$ The hashmaps are simply a way to identify relationships between entities and components. THis is dependent on how your game is set up, but I don't see an efficient way to guarantee that your bodys and transforms array will line up. This is just something you can't work around without either adding a layer of abstraction or planning your allocation. I feel I don't have the expertise to talk about scaling to multiple cores. Maybe find a question on threading and scaling or write your own. \$\endgroup\$ Jan 19, 2012 at 9:06
  • \$\begingroup\$ Scaling is easy when funcions are working on linear arrays - I can setup a range for each core and just run it. Thats why I'm trying to avoid hashmaps. I will be trying to redesign this entity system. I have to be really careful with caches misses - PS2 has very limited RAM, etc. BTW: Nothing is impossible :) \$\endgroup\$
    – mani3xis
    Jan 19, 2012 at 9:42
  • \$\begingroup\$ Nothing's impossible, but not everything is feasible ;). You can strive for simplicity and elegance of implementation, speed of execution, and memory consumption: pick two. When you do find your solution, please post it as an answer I'm certain I'm not the only one who'd like to see it. \$\endgroup\$ Jan 19, 2012 at 10:03

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .