Just look at conversion workflow, how it works, look at transform system and how it deal with parent-child relationships, look at Parent, LocalToParent components, Child buffer, LinkedEntity buffer.
I feel your pain jintaenate I had to look this up myself. Instead of a RTFM answer, here is how I abstracted SetParent for DOTS. I hope this helps
public static void SetParent(EntityManager dstManager, Entity parent, Entity child, float3 localTranslation, float3 localRotation, float3 localScale)
{
//set the child
if (!dstManager.HasComponent<LocalToWorld>(child))
dstManager.AddComponentData(child, new LocalToWorld { });
if (!dstManager.HasComponent<Translation>(child))
dstManager.AddComponentData(child, new Translation { Value = localTranslation });
else
dstManager.SetComponentData(child, new Translation { Value = localTranslation });
if (!dstManager.HasComponent<Rotation>(child))
dstManager.AddComponentData(child, new Rotation { Value = quaternion.Euler(localRotation) });
else
dstManager.SetComponentData(child, new Rotation { Value = quaternion.Euler(localRotation) });
if (!dstManager.HasComponent<NonUniformScale>(child))
dstManager.AddComponentData(child, new NonUniformScale { Value = localScale });
else
dstManager.SetComponentData(child, new NonUniformScale { Value = localScale });
if (!dstManager.HasComponent<Parent>(child))
dstManager.AddComponentData(child, new Parent { Value = parent });
else
dstManager.SetComponentData(child, new Parent { Value = parent });
if (!dstManager.HasComponent<LocalToParent>(child))
dstManager.AddComponentData(child, new LocalToParent());
//set the parent
if (!dstManager.HasComponent<LocalToWorld>(parent))
dstManager.AddComponentData(parent, new LocalToWorld { });
if (!dstManager.HasComponent<Translation>(parent))
dstManager.AddComponentData(parent, new Translation { Value = Vector3.one });
if (!dstManager.HasComponent<Rotation>(parent))
dstManager.AddComponentData(parent, new Rotation { Value = Quaternion.identity });
if (!dstManager.HasComponent<NonUniformScale>(parent))
dstManager.AddComponentData(parent, new NonUniformScale { Value = Vector3.one });
}
Another way of doing this is to have an entity have a component that hold another entity. Like
public struct Arm : IComponentData
{
public Entity armEntity
}
If you want to access the armEntity, have a job, access the component using ComponentDataFromEntity, and use another ComponentDataFromEntity to access the armEntity’s components
I agree the RTFM answer is not particularly helpful. To create simple parenting, on the child you have to add a ‘Parent’ component AND a ‘LocalToParent’ component.
entityManager.AddComponentData(myChildEntity, new Parent { Value = myParentEntity });
entityManager.AddComponentData(myChildEntity, new LocalToParent { });
This works for parenting normal entities, but you need more stuff to get it to work if you’re using the ConvertToEntity workflow and want use those things in your heirarchy. That’s where the ‘LinkedEntity’ buffer and ‘Child’ Buffers come in to play, I think, but I don’t know how to use those yet… so yeah, I am RTFM’ing it right now without much success.
Entities within a LinkedEntityGroup buffer are all created or destroyed together, giving you that traditional destroy the parent & destroy its children relationship from gameobjects.
pseudocode -
var buffer = EntityManager.AddBuffer<LinkedEntityGroup>(parentEntity);
buffer.add(childEntity);
Okay, so do LinkedEntityGroups work in a hierarchy too? For as an example, I have a hierarchy like this:
Player
|
+---> Arm
|
+---> Hand
I want to attach a ‘Sword’ entity as a child of the ‘Hand’ entity. So I do this:
entityManager.AddComponentData(SwordEntity, new Parent { Value = HandEntity });
entityManager.AddComponentData(SwordEntity, new LocalToParent { });
I understand that the LinkedEntityGroup will be on the ‘Player’ object, but not on the Arm or Hand objects.
So I add a LinkedEntityGroup to the ‘Hand’ Entity, then add the Sword to that? Or do I have walk the tree up to the root and add it to the ‘Player’ objects group?
// Just add the buffer to the hand entity and it works?
// (note: tried this and it doesn't seem to work for me)
var buffer = EntityManager.AddBuffer<LinkedEntityGroup>(HandEntity);
buffer.add(SwordEntity);
OR
// Add it to the root object
// (note: This works as expected - destroying the player destroys the sword)
var buffer = EntityManager.AddBuffer<LinkedEntityGroup>(PlayerEntity);
buffer.add(SwordEntity);
I guess I’m trying to avoid having to know what the root object is if I’m parenting something to a entity deeper in the tree. Maybe that’s not possible.
Also… what’s the Child buffer for that eizenhorn mentioned? I can’t seem to find an example of how to use it.
My understanding is the LinkedEntityGroup doesnt care about what entities are in a hierarchy or not, if an entity has a LinkedEntityGroup buffer any stored in that buffer will be created or destroyed along with said entity.
That said if a child entity has a linkedentitygroup and number of entities stored, and the parent has the child as a different linkedentity group and the parent is destroyed(or these can be unrelated hierarchy wise and only linked through the LinkedEntityGroup), I would assume all linkedentities of the child should be destroyed but I havent specifically tested that scenario.
The child buffer is just a buffer of all child entities a parent has, afaik it should be handled automatically(though having that list of child entities might be useful for certain situations).