More questions, yay.
I'm looking for a way to efficently implement 'nodes'. 'Nodes' being nodes in Ash, or Aspects in Artemis; that is to say, they are a collection of components an entiy must have for a system to affect said entity. EG: The movement system affects entities with position and velocity, so entities with those components have a 'movement' node which the movement system then effects.
Background:
So, my ES implementation is setup like so:
- I have a World object that has an entity manager and a system manager.
- The system manager keeps track of the various systems (that's about all I have right now, as I'm just starting to work on systems now).
- My entity manager manages entities and their components. It has a hash that takes in a component name and returns a component manager. It also has another hash that takes in a component name and return's a component ID. A component manager manages its (one type of) component. Basically, it keeps it's component storage (an array) as densely packed as possible (to save memory) and translates a component ID to the actual component data structure. The end result is that entity #5 may have position #0 (which the position component manager may translate to be x=100, y=50) and velocity #8 (which the velocity manager may translate to be x=-3, y=10).
The problem:
I originally designed the component manager as I did to keep the array densly packed to save memory and to speed up system execution. However, system execution is now complicated because the components that belong to an entity can be spread throughout the various component arrays (as seen above). This means, as it stands, the movement system can't take velocity at index 1 and apply it to the position component at index 1 because they can belong to different entities.
However, I really like the space savings offered by my current implementation of my component manager. If I have 3,000 entities and each entity only has 3 components, then, on average, each array is 1,000 big rather than the more naive each array is 3,000 big (as an example, I'm just throwing out numbers).
My solution:
The solution I've come up with is to implement 'nodes', data structures that contain components and have a one-to-one relationship with systems. EG: The movement system requires movement nodes, that contain the position and velocity components; the render system requires render nodes, that contain position and sprite components; etc.
Every time an entity is created or changed (components added/removed) a 'updateNodes' function is called that will update the nodes belonging to that entity. This means if an entity has a position, it does not have a movement node (requires position and velocity); however, when the entity has a velocity component added, a movement node is created which is then used in the movement system. Likewise for velocity being removed, the movement node is removed/destroyed and is no longer affected by the movement system.
Components in a node are pointers. This way if a component is altered (such as by the movement system), the component data is altered and is correct for all the other nodes that use that component (such as the render node, which is used by the render system and has the updated position value).
The problem I have with this potential approach is that it destroys caching. No longer can systems run along an array and update components and have prefetching work (for lack of a better term), because of the indirection I am now jumping around in memory and have lost a key aspect of Entity Component Systems.
To get around that, I could have nodes have a copy of the data; but now I run into the problem of 'what if a system changes a node's component, it's no longer the same for the other nodes that use the same component'.
So, as always, I'm curious as to what other people have done.