Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Resolved EndFrameParentSystem removes Parent component for children when destroying an entity

Discussion in 'Entity Component System' started by OcarinaBoy2049, Nov 23, 2020.

  1. OcarinaBoy2049

    OcarinaBoy2049

    Joined:
    Dec 7, 2019
    Posts:
    6
    I have a hierarchy of entities (A, B, C), and I want to destroy B and reparent C to A. This seems to be a bug in
    the EndFrameParentSystem to me. Here's a test I wrote to demonstrate the behaviour.

    Code (CSharp):
    1.        
    2. [Test]
    3.         public void ReparentTest()
    4.         {
    5.             var arch = m_Manager.CreateArchetype(
    6.                 typeof(Translation), typeof(Rotation), typeof(Parent), typeof(LocalToParent), typeof(LocalToWorld));
    7.  
    8.             var bottom = m_Manager.CreateEntity(arch);
    9.             var middle = m_Manager.CreateEntity(arch);
    10.             var top = m_Manager.CreateEntity(arch);
    11.             m_Manager.SetComponentData(top, new Parent { Value = middle });
    12.             m_Manager.SetComponentData(middle, new Parent { Value = bottom });
    13.  
    14.             World.GetOrCreateSystem<EndFrameParentSystem>().Update();
    15.  
    16.             Assert.IsTrue(m_Manager.HasComponent<Parent>(top)); //This is true
    17.  
    18.             m_Manager.SetComponentData(top, new Parent{Value = bottom});
    19.             m_Manager.DestroyEntity(middle);
    20.  
    21.             World.GetOrCreateSystem<EndFrameParentSystem>().Update();
    22.  
    23.             Assert.IsTrue(m_Manager.HasComponent<Parent>(top)); //This is false
    24.         }
    25.  
     
  2. OcarinaBoy2049

    OcarinaBoy2049

    Joined:
    Dec 7, 2019
    Posts:
    6
    Does anyone have a workaround for this?
     
  3. reeseschultz

    reeseschultz

    Joined:
    Apr 1, 2018
    Posts:
    21
    I slightly modified and ran your code. I'm using 0.16.0-preview.21 of Unity.Entities. I can confirm that destroying the
    middle
    (the parent) entity completely removes the parent component from
    top
    (the child).

    At first glance, it may seem that the more intuitive result would be that removing the
    middle
    entity should cause
    top
    's parent value to be
    Entity.Null
    . But! Imagine that were the case. Then, if we later queried some entities with parent components, we'd be irritated about resultant ones containing
    Entity.Null
    values ("but that one doesn't really have a parent anymore, does it?"). This is a hard design problem in terms of API usability, and I think I prefer the default. At least, I'm assuming it's intentional lol. You could check by reading the code in
    ParentSystem
    , or one of the associated tests.

    Here's a workaround version of your code, @OcarinaBoy2049:

    Code (CSharp):
    1. [Test]
    2. public void ReparentTest()
    3. {
    4.     var arch = m_Manager.CreateArchetype(typeof(Translation), typeof(Rotation), typeof(Parent), typeof(LocalToParent), typeof(LocalToWorld));
    5.  
    6.     var bottom = m_Manager.CreateEntity(arch);
    7.     var middle = m_Manager.CreateEntity(arch);
    8.     var top = m_Manager.CreateEntity(arch);
    9.  
    10.     m_Manager.SetComponentData(top, new Parent { Value = middle });
    11.     m_Manager.SetComponentData(middle, new Parent { Value = bottom });
    12.  
    13.     World.GetOrCreateSystem<EndFrameParentSystem>().Update();
    14.  
    15.     Assert.IsTrue(m_Manager.HasComponent<Parent>(top));
    16.  
    17.     m_Manager.DestroyEntity(middle);
    18.  
    19.     World.GetOrCreateSystem<EndFrameParentSystem>().Update();
    20.  
    21.     m_Manager.AddComponentData(top, new Parent { Value = bottom });
    22.  
    23.     World.GetOrCreateSystem<EndFrameParentSystem>().Update();
    24.  
    25.     Assert.IsTrue(m_Manager.HasComponent<Parent>(top));
    26. }
    With this code, both assertions should pass. Note that you can destroy the
    middle
    entity, then either skip a frame (if using
    [UnityTest]
    ) or run the
    EndFrameParentSystem
    as you are, and finally add a brand new parent component to
    top
    —you must use
    AddComponentData
    there instead of
    SetComponentData
    .
     
  4. OcarinaBoy2049

    OcarinaBoy2049

    Joined:
    Dec 7, 2019
    Posts:
    6
    After reading the code in the ParentSystem I discovered that entities get put in the `m_DeletedParentsGroup` if they have a `Child` component and do not have a `LocalToWorld`. So by removing the `Child` component before deleting the entity, the test works as expected.