Sign in to follow this  

Improving component system

This topic is 1100 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm working on upgrading my component based entity system. Right now I have a hierarchy of Entity objects within a Scene (which is itself just a special Entity). Each Entity has components that implement a Component interface that are basically a collection of callbacks. Components have onAttach, onUpdate, onDetach, etc. callback functions that are called when these events happen. The problem here though, is that I've got a really random memory access pattern by traversing through the hierarchy every frame and calling into each component. What I would like is to have a more linear memory access pattern where all components of the same type are updated together all at once.

 

I tried making it so my Component classes were just structures of data, and have a System that actually implemented the functionality. The problem with that though is actually tracking components. Should I require that when an Entity is created it will have a pointer to some sort of "SystemManager" that it can notify when Components are attached or detached? And if I do that, then how would I be able to retain support for my features like disabling entities and all their children? I can't just check the owner Entity of the Component to see if it's disabled, because that would throw another random memory access back in, and it would create more work when I have to traverse the hierarchy upward until the root to see if any parents are disabled.

 

Basically, all I want to do is be able to make my memory accesses more linear to improve cache performance while retaining my features (mainly creating a Scene in memory without setting it as active; and being able to disable an object and all its children). I don't care if I have to separate functionality from components, in fact I'd prefer to do so because of the extra opportunities for parallelism it presents in the future.

Share this post


Link to post
Share on other sites


Should I require that when an Entity is created it will have a pointer to some sort of "SystemManager" that it can notify when Components are attached or detached?

 

Is there a reason the entity needs to be in the picture when adding/removing components? If someone else is managing the component storage, then no "notifications" are needed. Instead of "hey entity, I'm adding a foo component to you", have it be "hey worldmanagerthing, I'm adding a foo component to entity 12345".

 


And if I do that, then how would I be able to retain support for my features like disabling entities and all their children?

 

Do you have functionality for deleting an entity and all its children? Maybe this could be similar, except that instead of the entity/components being reclaimed, they could be moved to some alternate storage area while disabled.

Share this post


Link to post
Share on other sites

The main reason the Entity is in the picture when adding components is so that I can access an Component directly with an index to it in the Entity. I guess if I used some sort of lookup table for entities and components in the scene then it wouldn't be too bad, although that would be some extra searching to add to it.

 

Yeah I've got a removeAllChildren method, and I've got a regular remove method that also cleans up the children. Basically what you're suggesting is that I recurse through the children when an entity is disabled and remove their components from the manager right?

Share this post


Link to post
Share on other sites

Just thought I'd share what I eventually decided on in case anyone else was interested. The responses I got were really helpful and made me start thinking about my component system in a different way. 

 

The way it's setup now, is I run a quick recursion through the tree of objects each frame, and add their components to update lists for that frame. I pay the cost of recursing through the entire scene hierarchy, but I still retained my hierarchies, enabling/disabling still works correctly, and my Entity/Scene management code has become simpler. I figure that I'll probably only be recursing 5 levels deep at max, because the simple objects making up the majority of most scenes are probably going to be self contained static meshes with no hierarchy anyways. I also handle initialization with flags on the components. Each component has flags, and one of the flags is just a "has been initialized" flag that gets set after initializing that component.

 

Anyways, I just figured I'd post what I ended up going with in case anyone found it interesting.

Share this post


Link to post
Share on other sites

out of curiosity, why the tree of entities?   what types of entities have child entities?  its seems a bit unusual:

 

"the simple objects making up the majority of most scenes are probably going to be self contained static meshes with no hierarchy anyways."

 

have you actually identified objects in the game that have hierarchies? or is this just a capability you anticipate needing?

 

so what type of objects have a hierarchy? i've heard of using tree hierarchies for renderables: "horse - rider - sword" type thing, but i've never heard of it used for entities.

Share this post


Link to post
Share on other sites

out of curiosity, why the tree of entities?   what types of entities have child entities?  its seems a bit unusual:

 

"the simple objects making up the majority of most scenes are probably going to be self contained static meshes with no hierarchy anyways."

 

have you actually identified objects in the game that have hierarchies? or is this just a capability you anticipate needing?

 

so what type of objects have a hierarchy? i've heard of using tree hierarchies for renderables: "horse - rider - sword" type thing, but i've never heard of it used for entities.

 

It's more convenient for gameplay code. If someone gets in a vehicle I can set their character to be parented to the vehicle and move everything with it automatically that way. I can attach weapon entities to bones, and I can keep the hitboxes attached to the bones easily too. Unity does it the same way. You've got a game object and a bunch of components and children attached to it. Also, by making each bone in a skeleton a game object I can write my animation system to work for all game objects instead of just skeletons.

 

Though if there was a clean way to retain that functionality and switch to a plain array of objects then I'd probably at least try it out since it would simplify things quite a bit. I guess I could implement the hierarchy as a component, or implement a scene graph as part of the rendering system instead... But it just seems like I would lose quite a bit of flexibility when hitboxes need to match up with animations.

Share this post


Link to post
Share on other sites

out of curiosity, why the tree of entities?   what types of entities have child entities?  its seems a bit unusual:
 
"the simple objects making up the majority of most scenes are probably going to be self contained static meshes with no hierarchy anyways."[/size]
 
have you actually identified objects in the game that have hierarchies? or is this just a capability you anticipate needing?[/size]
 
so what type of objects have a hierarchy? i've heard of using tree hierarchies for renderables: "horse - rider - sword" type thing, but i've never heard of it used for entities.

 
It's more convenient for gameplay code. If someone gets in a vehicle I can set their character to be parented to the vehicle and move everything with it automatically that way. I can attach weapon entities to bones, and I can keep the hitboxes attached to the bones easily too. Unity does it the same way. You've got a game object and a bunch of components and children attached to it. Also, by making each bone in a skeleton a game object I can write my animation system to work for all game objects instead of just skeletons.
 
Though if there was a clean way to retain that functionality and switch to a plain array of objects then I'd probably at least try it out since it would simplify things quite a bit. I guess I could implement the hierarchy as a component, or implement a scene graph as part of the rendering system instead... But it just seems like I would lose quite a bit of flexibility when hitboxes need to match up with animations.
I'd really recommend against using entity parent/child relationships to represent skeletal attachments -- this is basically scene-graphs all over again.

There's other properties besides attachments that deserve parent/child relationships - e.g.
* if you place a mesh as a child of a material, should it use that material?
* if a material is a child of a camera, should it render the camera to a texture and then use that's it's colour?
* if a flame-area-of-effect is a child of a flame-thrower, should their lifetimes be bound together (should deleting the weapon delete the flame)?
* if a grenade is a child of a player, should it appear in their inventory?

Old school scene graphs used to do all that and more...

You can't choose to support everything here, because many are contradictory - if I put a cup on a table, and parent it to the table so they move together, then I don't want the cup to be deleted if the table is destroyed...

Personally, I'd reserve entity parenting only for lifetime management - the same as lifetime management in C++.

To implement a transform hierarchy, I'd have a transform component with a matrix and a parent-transform-id. That's an array of matrices and an array of indexes.
Entities with positions can have a transform component ID. Skeletons can have an array of transforms component IDs.

The root bone of a player can then set a vehicle's seat bone as it's parent, without the player entity actually being a child of the vehicle.

If you have other relationships between components, you can implement them the same way, instead of hijacking entity connections themselves.

Share this post


Link to post
Share on other sites

That sounds like a pretty convenient way to do it... And it frees me from the transform hierarchy when I'm doing the 2D rendering for interface and HUD. I'll try a quick prototype and see what kind of results I get. Attaching weapons and hitboxes is the main concern I had, but using transform components to build the hierarchy should fix that.

Share this post


Link to post
Share on other sites


Though if there was a clean way to retain that functionality and switch to a plain array of objects then I'd probably at least try it out since it would simplify things quite a bit.

 

one possibility:

use an array[max_object] of objects.

each object has a parent_ID.

each object has a num_childeren (where max_children = 10 or whatever)

each object has an array[max_children] of child_IDs.

 

parent ID lets you traverse up the hierarchy.

child ID lets you traverse down the hierarchy.

a parent id of -1 means no parent.

num_children=0 means no children.

 

 

pros: fast arrays, can be iterated quickly. can be a static data structure.

cons: limited to max_objects, max_children.

 

this is a flat array implementation of a tree, a variation on the flat array implementation of a doubly linked list (IE one that has multiple "next" pointers).

 

i like the idea of object hierarchies for movement. i only use that type of thing in one place - moving entities and dropped objects aboard moving rafts. i render equipment using hierarchies, but don't consider them objects, simply inventory items.

 

converting my non-hierarchy entity list to this style would be straightforward. add the parent and child variables, and modify update to additionally apply results to any offspring. when an entity boards or disembarks from a raft, set parent and child variables for the entity and raft. max_children could be a problem if they want to drop 100 objects on the deck! <g>.

Share this post


Link to post
Share on other sites

Sean, I saw your videos on game spaces and data-driven design not too long ago. You're correct in that you can find a happy medium between intuitive OO code cache-friendly performance. Personally I've only seen it really count in my programs when it comes to managing graphics-related resources, so I do a ton of pooling of textures and meshes, and instance transforms to reduce state changes.

 

The blog you linked to looks like a pretty good implementation of data-oriented ECS. Shows that the author has prior real-world experience in game coding for performance. On the other hand, it doesn't sound like something you'd recommend if you already made your own kind of ECS framework which still does the job pretty well after testing it with many more components than you would actually use. Refactoring your code at that point of development seems almost useless if it's for that particular case use, while it's better off attempting it for a brand new game.

 

One thing I still don't fully understand about this type of ECS design, though. With entities as ID's, where should the component pools reside if a single system needs to work on two or more different types of components? Or should it only be one component type-per-system in this case?

Share this post


Link to post
Share on other sites

Another solution for dealing with related bone transforms is to consider them as higher-level things of their own rather than an explicit parent-child relationship.  Think about how a weld joint works in a physics engine.  This may not always be the best way to do it but it provides an elegant solution to situations such as the presented case of the cup on the table, where neither entity should be dependent on the other.

 

And when it comes to using packed, unordered component pools with systems that operate on multiple component types, you should have an array acting as a layer of indirection that maps IDs to offsets within the pool.  This structure can also deal with handle invalidation through "magic numbers".  Again, BitSquid has a good article on this concept.  If you're worried about cache coherency when it comes to these indirected accesses, my advice would be to deal with different object archetypes in heterogeneous ways.  For example, if not every entity has a velocity while every entity has a position, separate your entities into "static" and "dynamic" pools.  That way, your "dynamic" entities can keep their position and velocity components packed and correlated.

Edited by Boreal Games

Share this post


Link to post
Share on other sites

And when it comes to using packed, unordered component pools with systems that operate on multiple component types, you should have an array acting as a layer of indirection that maps IDs to offsets within the pool.  This structure can also deal with handle invalidation through "magic numbers".  Again, BitSquid has a good article on this concept.  If you're worried about cache coherency when it comes to these indirected accesses, my advice would be to deal with different object archetypes in heterogeneous ways.  For example, if not every entity has a velocity while every entity has a position, separate your entities into "static" and "dynamic" pools.  That way, your "dynamic" entities can keep their position and velocity components packed and correlated.

 

So the array to map IDs to different places in the pool is like a database table that stores relationships between entries in other tables? That's what I get from it being a "layer of indirection". Also, then it sounds like the component pools would not be inside of the system (but to me, it doesn't make sense for a system object to store components anyways, just needs to manipulate them). Looking through my code nearly all my Systems work on more than one type.

 

Splitting up the pools when the entities have slightly different behavior sounds like a good idea too, and easy to understand. Looks like I'll distinguish the "static" from "dynamic" entities for those that have a position component.

 

My idea is to have all the Position components in one array and those that belong to "dynamic" entities would be ordered from the beginning of the array, with the Positions of "static" ones afterwards. In practice most of my entities with a Position would not have a Velocity and therefore be static.

Share this post


Link to post
Share on other sites

in its most generalized form, an ECS usually looks something like this:

 

first you have a list of entities.

 

each entity has some sort of pointers or IDs referencing their components

 

then you have lists for each type of component.

 

and you have methods that operate on components.and / or component lists.

 

the list of entities just tells you where an entity's data is. the component lists hold the actual data, divvied up by component type. note that a render or update method could also be considered a component type.

Share this post


Link to post
Share on other sites

This topic is 1100 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this