Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

How to temporarily exclude entity from RenderMeshSystem?

Discussion in 'Graphics for ECS' started by Bas-Smit, Feb 15, 2019.

  1. Bas-Smit

    Bas-Smit

    Joined:
    Dec 23, 2012
    Posts:
    274
    I've been playing around with ecs for a while now, but I haven't come across a way to temporarily deactivate an entity. I would like to have a pool of meshes that can be reused. When I need one I will update the verts and use it with a RenderMesh component. Would I just keep the meshes and add/remove entities as and when required?

    Cheers, Bas
     
  2. MostHated

    MostHated

    Joined:
    Nov 29, 2015
    Posts:
    1,235
    There is probably a better way but I would imagine if you had a component that simply stored which mesh and material the entity was supposed to have on it you could then simply remove the meshrenderer component when you need to, then when you want it back just add it again and populate it with the stored mesh and material again? I do know that adding / removing components in ECS is waaayyyy more performant than the classic gameobject disable/enable.

    I have not yet heard of a way to "disable" something besides an actual system aside from just removing the component. It would be good to know this though if someone knows of a better way?
     
  3. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,754
    I haven't venture yet deep into culling mesh renderers, but I would give a shot and test, if culled entity based meshes save on ticks.
     
  4. jdtec

    jdtec

    Joined:
    Oct 25, 2017
    Posts:
    302
    I asked a similar question. There is also the Disabled tag component.

    Although this is a similar method in that you still add/remove a component, there is the possibility of better optimisation for empty tag components in the future, which may make it preferable.
     
  5. RecursiveEclipse

    RecursiveEclipse

    Joined:
    Sep 6, 2018
    Posts:
    298
    From my testing, empty tag components do get better add/remove times already. That is what is what was recommended by joachim ante, as they will be improving on it in the future.
     
    jdtec likes this.
  6. Srokaaa

    Srokaaa

    Joined:
    Sep 18, 2018
    Posts:
    169
    I couldn't use the Disabled component because I wasn't able to Render entities again once I added Disabled component to any of them. Here is a system I wrote that makes entites render-able only in some time-frame but surely you can modify it to suit your needs:


    Code (CSharp):
    1.     public class LevelTimeCullingSystem : JobComponentSystem
    2.     {
    3.         [Inject] private EndFrameBarrier _endFrameBarrier;
    4.  
    5.         protected override JobHandle OnUpdate(JobHandle inputDeps)
    6.         {
    7.             var showHandle = new ShowJob
    8.             {
    9.                 CommandBuffer = _endFrameBarrier.CreateCommandBuffer().ToConcurrent()
    10.             }.Schedule(this, inputDeps);
    11.             var hideHandle = new HideJob
    12.             {
    13.                 CommandBuffer = _endFrameBarrier.CreateCommandBuffer().ToConcurrent()
    14.             }.Schedule(this, showHandle);
    15.             return hideHandle;
    16.         }
    17.  
    18.         [RequireComponentTag(typeof(Frozen))]
    19.         private struct ShowJob : IJobProcessComponentDataWithEntity<LevelTimeCulled,
    20.             LevelTime>
    21.         {
    22.             public EntityCommandBuffer.Concurrent CommandBuffer;
    23.  
    24.             public void Execute(Entity                       entity,
    25.                                 int                          index,
    26.                                 ref LevelTimeCulled culling,
    27.                                 ref LevelTime       levelTime)
    28.             {
    29.                 if (levelTime.Time > culling.AppearanceTime &&
    30.                     levelTime.Time < culling.DisappearanceTime)
    31.                 {
    32.                     CommandBuffer.RemoveComponent<Frozen>(index, entity);
    33.                 }
    34.             }
    35.         }
    36.  
    37.         [RequireSubtractiveComponent(typeof(Frozen))]
    38.         [RequireComponentTag(typeof(LocalToWorld))]
    39.         private struct HideJob : IJobProcessComponentDataWithEntity<LevelTimeCulled,
    40.             LevelTime>
    41.         {
    42.             public EntityCommandBuffer.Concurrent CommandBuffer;
    43.  
    44.             public void Execute(Entity                       entity,
    45.                                 int                          index,
    46.                                 ref LevelTimeCulled culling,
    47.                                 ref LevelTime       levelTime)
    48.             {
    49.                 if (levelTime.Time < culling.AppearanceTime ||
    50.                     levelTime.Time > culling.DisappearanceTime)
    51.                 {
    52.                     CommandBuffer.AddComponent(index, entity, default(Frozen));
    53.                     CommandBuffer.RemoveComponent<LocalToWorld>(index, entity);
    54.                 }
    55.             }
    56.         }
    57.     }
    58.  
    It works by Removing LocalToWorld and adding Frozen component
     
    Last edited: Feb 16, 2019
  7. DenizCetinalp

    DenizCetinalp

    Joined:
    Feb 8, 2014
    Posts:
    16
    I switched to adding/removing Disabled component not too long ago.

    Code (CSharp):
    1.     private NativeArray<Entity> CreateEntities(List<RenderMesh> meshRenderers, bool hideOnCreate = false)
    2.     {
    3.         NativeArray<Entity> instances = new NativeArray<Entity>(meshRenderers.Count, Allocator.Persistent);
    4.  
    5.         for (int i = 0; i < meshRenderers.Count; i++)
    6.         {
    7.             Entity entity = m_entityManager.CreateEntity(m_entityArchetype);
    8.             m_entityManager.SetComponentData(entity, new Position { Value = transform.position });
    9.             m_entityManager.AddSharedComponentData(
    10.                 entity,
    11.                 meshRenderers[i]
    12.             );
    13.  
    14.             if (hideOnCreate)
    15.                 m_entityManager.AddComponent(entity, typeof(Disabled));
    16.  
    17.             instances[i] = entity;
    18.         }
    19.  
    20.         return instances;
    21.     }
    22.  
    23.     private void ShowEntities(int level)
    24.     {
    25.         m_entityManager.RemoveComponent(m_NativeEntities[level], typeof(Disabled));
    26.     }
    27.  
    28.     private void HideEntities(int level)
    29.     {
    30.         m_entityManager.AddComponent(m_NativeEntities[level], typeof(Disabled));
    31.     }
     
  8. Bas-Smit

    Bas-Smit

    Joined:
    Dec 23, 2012
    Posts:
    274
    Thanks for the info, adding and removing Disabled component works for me. Similarly there is the Frozen component. Note that adding removing components is potentially slow:

    All structural changes have hard sync points. CreateEntity, Instantiate, Destroy, AddComponent, RemoveComponent, SetSharedComponentData all have a hard sync point. Meaning all jobs scheduled through JobComponentSystem will be completed before creating the Entity, for example. This happens automatically. So for instance: calling EntityManager.CreateEntity in the middle of the frame might result in a large stall waiting for all previously scheduled jobs in the World to complete.

    See EntityCommandBuffer for more on avoiding sync points when creating entities during game play.
     
    Last edited: Feb 19, 2019