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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

SetActive for descendants in ECS

Discussion in 'Entity Component System' started by Yuriy_Sevastyanov, Feb 5, 2020.

  1. Yuriy_Sevastyanov

    Yuriy_Sevastyanov

    Joined:
    Apr 9, 2017
    Posts:
    25
    Hello, everyone!
    I want to be able to turn on and turn off a group of game objects by parent game object:
    ParentGameObject
    ChildOne
    ChildTwo
    AnotherDescendant​

    It would be easy to do it for MonoBehaviour, you just call ParentGameObject.SetActive() and all descendants would be disabled.
    But when I ConvertToEntity ParentGameObject the parent<-->child relationships are disappeared, and then when I add the Disabled component to the ParentGameObject entity it doesn't affect on descendants.
    I found two ways to approach the same behavior:
    1. Before ConvertToEntity I can iterate all descendants and add a component like that:
      Code (CSharp):
      1. public struct DisabledChild: IComponentData
      2. {
      3.   public int ParentId;
      4.   public bool WasDisabledBefore;
      5. }
      And then create a system that will filter by ParentId and add or remove Disabled component.
    2. Add Physics Body component that adds Child components to descendants.
      And then create a system that will iterate by children and add or remove Disabled components.
    Is there a more elegant way?
     
  2. Srokaaa

    Srokaaa

    Joined:
    Sep 18, 2018
    Posts:
    169
    That's how I recursively access children:

    Code (CSharp):
    1.  
    2.         protected override JobHandle OnUpdate(JobHandle inputDeps)
    3.         {
    4.             var commandBuffer = _endSimulationEntityCommandBufferSystem.CreateCommandBuffer().ToConcurrent();
    5.             var childrenBufferFromEntity = GetBufferFromEntity<Child>(true);
    6.             inputDeps = Entities
    7.                 .WithAll<Destroyed>()
    8.                 .WithReadOnly(childrenBufferFromEntity)
    9.                 .ForEach((Entity entity, int entityInQueryIndex) =>
    10.                 {
    11.                     EntitiesHelpers.DestroyEntitiesRecursive(entity,
    12.                         entityInQueryIndex,
    13.                         ref commandBuffer,
    14.                         in childrenBufferFromEntity);
    15.                 }).Schedule(inputDeps);
    16.             _endSimulationEntityCommandBufferSystem.AddJobHandleForProducer(inputDeps);
    17.             return inputDeps;
    18.         }
    19.  
    Code (CSharp):
    1.     static class EntitiesHelpers
    2.     {
    3.         public static void DestroyEntitiesRecursive(Entity entity,
    4.             int                                            entityInQueryIndex,
    5.             ref EntityCommandBuffer.Concurrent             commandBuffer,
    6.             in  BufferFromEntity<Child>                    childrenBufferFromEntity)
    7.         {
    8.             commandBuffer.DestroyEntity(entityInQueryIndex, entity);
    9.             if (childrenBufferFromEntity.Exists(entity))
    10.             {
    11.                 var children = childrenBufferFromEntity[entity];
    12.                 for (var index = 0; index < children.Length; index++)
    13.                 {
    14.                     DestroyEntitiesRecursive(children[index].Value,
    15.                         entityInQueryIndex,
    16.                         ref commandBuffer,
    17.                         in childrenBufferFromEntity);
    18.                 }
    19.             }
    20.         }
    21.     }
    22.  
     
  3. Yuriy_Sevastyanov

    Yuriy_Sevastyanov

    Joined:
    Apr 9, 2017
    Posts:
    25
    @Srokaaa Thank you for sharing. I also use a similar way to destroy children.
    But I need to disable/deactivate not to destroy. It also requires Physics Body to build a Parent-Child relationship as I mentioned on p.2