Advertisement Jump to content
Sign in to follow this  
Alex B.

Entity Component System and Parent Relations

This topic is 1768 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

Hi there,

 

our team is trying to build an data oriented entity component system for our game.

 

We understood in most cases the benefits of the system. But we are struggeling with the parent relationships a scene graph qould give us. For example you got a transformation change of a matrix. So all childs related to this matrix get updated in relation to the parent.

 

How can such relations be built in an ECS? Or do we have to run a scenegraph together wit h the ECS?

 

Thank you!

Share this post


Link to post
Share on other sites
Advertisement

I was thinking about this myself. The most straight forward way might be to make the transform component be a some kind of scene node. Still I am not sure how you attach e.g. a weapon entity to the bone of a skeleton in this case.   

Share this post


Link to post
Share on other sites
You can sort the objects stored in the scene graph by parent->child relationships. If you have a parent A with two children C and D and then another root node B, you'd want it sorted ACDB. Resorting every frame (possibly in parallel) is just fine. Now you can just iterate through the list of scene nodes and update matrices with back-references. Locality of reference will be high, cache coherency will be strong. This contiguous array of scene nodes can be veyr useful for certian rendering architecture,s too.

Note that a scene node is not an entity, nor is it necessary a component all its own. One entity might have multiple scene nodes representing a complex dynamic object. You should end up with separate object modules: your game object module, your scene node module, your physics module, etc. The components are just there to associate game objects with the other modules. You're mostly forced to work this way in bigger scale games where you are usually using a third-party physics library or graphics middleware (Umbra, FaceGen, Granny, etc.).

Share this post


Link to post
Share on other sites

For example you got a transformation change of a matrix. So all childs related to this matrix get updated in relation to the parent

That should be a detail of the transformation component, hidden inside the transformation system.
 
You don't need entities to have a parent/child relationship just because your transformation components do.
 
For example, what if you had a different component that had a different parent/child relationship?
e.g. when a vampire bites someone, they become a "child" vampire of this one. If you kill a vampire, all of it's "children" also die.
Bob bites fred. Fred is now a "child vampire" of Bob.
Fred gets into a car. Fred is now a "child transform" of the car.
 
If you're using the entity (instead of the component) to represent parent/child relationships, then everything breaks down here. Is the Fred entity a child of Bob entity or the Car entity?

Edited by Hodgman

Share this post


Link to post
Share on other sites

There are several possible solutions. I'm fine with the following one:

 

A Placement component defines a position and orientation for the entity in the world. This component is a storage, e.g. it does not update itself. Updaters for Placement may be an animation or a behavior component (or a script if you like). One possible behavior component is Parenting which implements forward kinematics (other behaviors are Aiming, Aligning, Tracking, Interposing, Billboarding, Grabbing (a special kind of "parenting" that reflects holding or equipping), ... ). Such behavior components can have their own variables. E.g. the local placement of a child entity is stored within its Parenting component. WIthout any write access to a Placement, the entity is in fact static w.r.t. its position and orientation. I've chosen this way because forward kinematic is just one way of controlling a Placement, and it is not special compared to others.

 

Other relations between entities could be expressed similarly. Again other relations that may be expressed by uber scene graphs are only reflected partly in components themselves. E.g. while a collision volume may be an own component or part of a component, the structure of managing colliders and detecting / resolving collision is a task placed over components, and hence should always be done in a sub-system (its the way I prefer handling components anyway). 

 

 

EDIT: I recommend not to use scene graphs at all. Notice that a scene graph is a sole hierarchy which is used to express, well, everything. One should instead use structures that are well suited to solve the problems one by one. That said, also ECS can be "misused" similarly to how a scene graph can be. Hence I prefer to look at ECS as a structure to compose the scene, perhaps like a flattened graph where all relations are made explicit. From this some more specialized structures are extracted / derived and handled at runtime inside the belonging sub-systems. The transformation graph and the collision resolution are examples of this. 

Edited by haegarr

Share this post


Link to post
Share on other sites
Hi, thanks for the information!

Okay so everything seams to be doable with an ECS :o

But the relation thing I still don't understand.

For example: i got a car with 4 wheels.
Car body gets turned by 90°. So the wheels would have to geht turned relative to the car body.

Can you explain how that could be done with the ECS approach?
Maybe with a code snippet.

Thank you very much guys!

Share this post


Link to post
Share on other sites

Well, question is whether a wheel as part of a car should be its own entity at all… But nevertheless, let's use it as an example. Of course, I describe it the way I'm doing things. Other solutions are possible as well, you know. A description in code snippets is meaningless until the API is known, but the API is engine specific; so I stick with a verbose description.

 

Create and entity for the car body. Create another entity for a wheel. Create a Placement component for the 1st and another for the 2nd entity. Because of the existence of the Placement components in their initial state (i.e. identity transform) both entities are located at the world's origin and are facing along, say, the z axis. Notice that both entities exist side by side and not hierarchically. I allow nesting entities in the editor not for the sake of dependency but just for a logical grouping, allowing the designer to straighten up things to its wish.

 

Because there is nothing set-up that alters the both Placements, both entities are static. Now create a Parenting component and assign it to the wheel entity. The Parenting component is assigned to the entity whose Placement component is to be controlled, i.e. the "child" entity. In order to complete this step you obviously need to tell which entity the "parent" role plays. So attach the car body's entity to the Parenting controller's parent slot.

 

Now we have a mechanism installed to the wheel that computes the value of the entity's Placement as usual for parenting, i.e. when using column vectors:

     my_entity_Placement_value := parent_Placement_value * local_placement

 

Nothing has changed on screen because both right hand side transforms are still identity transforms. So translate the wheel to where it should be located relative to the car body's placement. In fact you do not alter the wheel's Placement directly but the wheel's Parenting local placement value.

 

When you compare this with a scene graph solution, then the parenting is not expressed by a wheel node below a transform node below a car node, but (when still using the term "node") a transform node below a wheel node besides a car node.

 

The sense of this set-up will become probably more clear when thinking of other mechanisms (I'm supporting 12 different mechanisms at the moment). Let us have a look at targeting. Let's say you have a Tracking component installed to a weapon, and it tracks the Placement of an enemy. For sure weapon and enemy are 2 real distinct entities, and putting the one as node of a scene graph into the other makes no sense. Instead, both live side by side in the CES and the one is explicitly expressed to target the other by the current existence of a Tracking component.

 

Besides the mechanisms mentioned above, there is another kind of controller that fits into this set-up: Animation. Let's say the animation sub-system currently runs a track that changes the local rotation of the wheel's Parenting component. Voila, the wheel rotates in place, and it moves with the car body.

Edited by haegarr

Share this post


Link to post
Share on other sites
I'm interested in this as well. I have a couple questions about the system you described Haegarr:

1) How does your system know what position component to update? In your example, you have a placement component that stores a local position, which is the position relative to the parent's position. Now suppose someone kicks the wheel. How does the physics system know to update the Parenting component's local_placement rather than the Position component's position?

2) How does the rendering system resolve the "final" position of the entity?

3) And lastly, what happens if there are several different types of these parenting-type components (you mention having 12 different ones) on one entity? Or is that just considered a no-no?

Share this post


Link to post
Share on other sites


Say we have a weapon entity and we want to attach it to the right hand of of the skeleton in another entity. How do we solve this?

I solve this using what I call the Grabbing mechanism. It is a kind of extended parenting and works as follows:

 

An entity that can be grabbed gets a Grip component. An entity that is able to grab something gets a Grab component. Both of these components have a set of key values. One of the key values of a Grip needs to be identical to one of the key values of Grab, then the Grab is allowed to be paired with the Grip. This is used to control what entities can be held by which entities and how.

 

A Grip has a local placement which defines an anchor point and orientation. A Grab also has such a placement. The anchor of a Grab is usually linked to a bone of a skeleton. The anchor of a Grip is usually static.

 

When a Grabbing is established then the Grab is paired with a Grip. This is marked in the Grab by referring to the Grip and vice-versa. The task is then to make the two anchors coincident. When the local placement of the Grab is updated e.g. due to skeletal animation, its world position can be computed as

    grab_global := entity_with_Grab__Placement * grab_local

The corresponding formula for the Grip is

    grip_global := entity_with_Grip__Placement * grip_local

and both should be identical, hence
     entity_with_Grab__Placement * grab_local = entity_with_Grip__Placement * grip_local
so that
    entity_with_Grip__Placement = entity_with_Grab__Placement * grab_local * inv_grip_local

 

In other words, Grabbing sets the grabbed entity's Placement to the value as computed above. (Remember that Placement components ever store a world position.)

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!