Jump to content

  • Log In with Google      Sign In   
  • Create Account


Entity Component System and Parent Relations


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
11 replies to this topic

#1 Alex B.   Members   -  Reputation: 237

Like
0Likes
Like

Posted 05 March 2014 - 02:58 PM

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!



Sponsor:

#2 Dirk Gregorius   Members   -  Reputation: 713

Like
0Likes
Like

Posted 05 March 2014 - 06:35 PM

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.   



#3 SeanMiddleditch   Members   -  Reputation: 3872

Like
0Likes
Like

Posted 05 March 2014 - 09:49 PM

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.).

#4 Hodgman   Moderators   -  Reputation: 27668

Like
3Likes
Like

Posted 05 March 2014 - 11:28 PM

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, 05 March 2014 - 11:28 PM.


#5 haegarr   Crossbones+   -  Reputation: 3750

Like
0Likes
Like

Posted 06 March 2014 - 03:02 AM

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, 06 March 2014 - 03:13 AM.


#6 Alex B.   Members   -  Reputation: 237

Like
0Likes
Like

Posted 06 March 2014 - 06:03 AM

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!

#7 haegarr   Crossbones+   -  Reputation: 3750

Like
0Likes
Like

Posted 06 March 2014 - 07:16 AM

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, 06 March 2014 - 07:17 AM.


#8 Dirk Gregorius   Members   -  Reputation: 713

Like
0Likes
Like

Posted 06 March 2014 - 11:34 AM

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?



#9 Telanor   Members   -  Reputation: 1281

Like
0Likes
Like

Posted 06 March 2014 - 11:55 AM

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?

#10 haegarr   Crossbones+   -  Reputation: 3750

Like
0Likes
Like

Posted 06 March 2014 - 02:16 PM


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.)



#11 haegarr   Crossbones+   -  Reputation: 3750

Like
1Likes
Like

Posted 06 March 2014 - 03:10 PM


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?

Nope. A Placement component ever stores a global placement (I use the term placement for a combination of position and orientation). When an entity has a Placement component it is placed in the world. Notice that a global placement makes sense by itself but a local placement does not because the latter requires a reference frame. The local placement e.g. within the Parenting component is not a component but a member value. I used a uppercase "Placement" for component (like written as a classname) and a lowercase "placement" otherwise.

 

So the question is how does the physics system know whether to update the local placement or the global Placement of the wheel. So read on ...

 


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

It doesn't, because it need not. Notice that the rendering sub-system is the last executed during an iteration of the game loop. When it comes into play all of animation, physics, collision resolution and so on is already done. Hence all Placement components are up-to-date and, because those components ever store the global placement, ready-to-use.

 

Nevertheless the Placement instances which are controlled in some way need to be updated. Notice that this problem is unrelated to CES. Animation controlled placements are driven when the animation system is updating, of course. Placements that are controlled by what I call mechanisms are updated when the belonging sub-system (named SpatialServices) is updated. You can solve this problem using a dependency graph with or without dirty state propagation, as usual, where the edges of the graph are defined by the components implementing the mechanisms. Physics and collision resolution can work as usual.

 


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?

It makes no sense to run competing controllers on the same value. Well, this brings up the question what the controlled value is. A placement can be seen as one compound value, as a position and an orientation, or as 3 position scalar channels and 3 orientation scalar channels. The latter one is nowadays typical for 3D content creation packages but probably too fine grained for games. The former one is perhaps too coarse. I used to use the separate position and orientation channels. Hence a controller may control both or one of both channels. For example, the Tracking component naturally controls the orientation only, while an Orbiting controls both channels. If meaningful then the control by a component can be switched on or off. With respect to physics, the controlled channels are constrained.

 

Additionally, it is valid to have several controlling components if they don't compete because all but one is disabled. For example it is okay to have several Grip components on an entity as long as at most one of them is paired with a Grab.



#12 Alex B.   Members   -  Reputation: 237

Like
0Likes
Like

Posted 16 March 2014 - 02:07 PM

Thank you very much guys, that helped us a lot!

 

Otherwise we would have ended developing a ECS and a Scenegraph! :P






Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS