Search Unity

How to enable/disable renderer of entity?

Discussion in 'Graphics for ECS' started by ParametrixFX, May 24, 2019.

  1. ParametrixFX

    ParametrixFX

    Joined:
    Nov 14, 2018
    Posts:
    18
    Hi,

    Say I want to not render an entity at this moment and render it 10s later. What would be the best approach?
     
  2. Opeth001

    Opeth001

    Joined:
    Jan 28, 2017
    Posts:
    1,117
    try the new EntityManager.SetEnabled API, if it still not working just move them to another World.
     
  3. ParametrixFX

    ParametrixFX

    Joined:
    Nov 14, 2018
    Posts:
    18
    It seems like SetEnabled(false) disable the entity completely, not just the mesh renderer (The entity is not processed in the next frames). I just need it not to be rendered but still be processed by other systems.

    Also, I'm not sure if this is a bugged, but when I SetEnabled(false) to a parent Entity, the child entities are not also disabled. The parent entity has a LinkedEntityGroup and Child components
     
  4. Opeth001

    Opeth001

    Joined:
    Jan 28, 2017
    Posts:
    1,117
    I never had to disable renderering to specific entities and I'm not sure that the Hybred renderer system is handling it.
    My seggestion is when you are about to make an entity invisible take it's renderer SharedComponent, add it to a new entity and add the entity as Component Data to get a direct link between to the invisible and the entity holding it's renderer ,then remove the renderer SCD from the original entity.
    Note: the renderer will not renderer the original entity neither it's componentHolder cause it doesn't contain position, rotation scale ...
    Certainly it's not an optimized way of doing it cause removing and adding SCD is havy, but it's a workaround until unity will handle this use case.( I'm not even sure if unity is not already handling it )
     
    ParametrixFX likes this.
  5. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,761
    It's been a while and i've made some changes but here is my solution to this.

    Code (CSharp):
    1. // <copyright file="HiddenSystem.cs" company="BovineLabs">
    2. //     Copyright (c) BovineLabs. All rights reserved.
    3. // </copyright>
    4.  
    5. namespace BovineLabs.Vision.Systems
    6. {
    7.     using System;
    8.     using BovineLabs.Common.Containers;
    9.     using BovineLabs.Vision.Components;
    10.     using BovineLabs.Vision.Model;
    11.     using Unity.Collections;
    12.     using Unity.Entities;
    13.     using Unity.Mathematics;
    14.     using Unity.Rendering;
    15.     using UnityEngine;
    16.     using UnityEngine.Assertions;
    17.  
    18.     /// <summary>
    19.     /// The mode for hiding the <see cref="HiddenSystem"/> uses.
    20.     /// </summary>
    21.     public enum HideMode
    22.     {
    23.         /// <summary>
    24.         /// Hide by manipulating the <see cref="WorldBounds"/> setting them outside the culling area.
    25.         /// </summary>
    26.         WorldBounds,
    27.  
    28.         /// <summary>
    29.         /// Hide by removing the <see cref="RenderMesh"/>.
    30.         /// </summary>
    31.         RenderMesh,
    32.     }
    33.  
    34.     /// <summary>
    35.     /// Manages the various methods of entities being hidden.
    36.     /// </summary>
    37.     [UpdateInGroup(typeof(VisionGroup))]
    38.     [UpdateAfter(typeof(RevealedSystem))]
    39.     public class HiddenSystem : ComponentSystem
    40.     {
    41.         /// <summary>
    42.         /// Gets the fake bounds to ensure the mesh is culled from the render systems.
    43.         /// </summary>
    44.         internal static readonly AABB OutOfBounds = new AABB
    45.         {
    46.             Center = new float3(-1000000, -1000000, -1000000),
    47.             Extents = new float3(0, 0, 0),
    48.         };
    49.  
    50.         private readonly HideMode mode;
    51.         private readonly Map<RenderMesh, int> meshes = new Map<RenderMesh, int>();
    52.         private readonly ComponentType[] hideTypes;
    53.  
    54.         private int meshIndex = 0;
    55.  
    56.         private EntityQuery hideQuery;
    57.         private EntityQuery showQuery;
    58.         private EntityQuery hidePureQuery;
    59.         private EntityQuery hideMeshRendererQuery;
    60.         private EntityQuery thisShowPureQuery;
    61.         private EntityQuery showMeshRendererQuery;
    62.  
    63.         /// <summary>
    64.         /// Initializes a new instance of the <see cref="HiddenSystem"/> class.
    65.         /// </summary>
    66.         /// <remarks>
    67.         /// This constructor should not be used instead it needs to be manually setup, usually in <see cref="ICustomBootstrap"/>.
    68.         /// It's included so that new, empty projects don't throw errors when auto generating.
    69.         /// <see cref="DisableAutoCreationAttribute"/> is not used because it does not fit all custom bootstrap solutions.
    70.         /// </remarks>
    71.         public HiddenSystem()
    72.         {
    73.             this.Enabled = false;
    74.             this.hideTypes = new ComponentType[0];
    75.         }
    76.  
    77.         /// <summary>
    78.         /// Initializes a new instance of the <see cref="HiddenSystem"/> class.
    79.         /// </summary>
    80.         /// <param name="mode">The mode for hiding.</param>
    81.         /// <param name="hideTypes">Types that hide an entity.</param>
    82.         public HiddenSystem(HideMode mode, params ComponentType[] hideTypes)
    83.         {
    84.             Assert.IsNotNull(hideTypes, "No hide types specified.");
    85.             Assert.AreNotEqual(0, hideTypes.Length, "No hide types specified.");
    86.  
    87.             this.mode = mode;
    88.             this.hideTypes = hideTypes;
    89.         }
    90.  
    91.         /// <inheritdoc />
    92.         protected override void OnCreate()
    93.         {
    94.             this.hideQuery = this.GetEntityQuery(new EntityQueryDesc
    95.             {
    96.                 None = new[] { ComponentType.ReadOnly<Hidden>(), },
    97.                 Any = this.hideTypes,
    98.             });
    99.  
    100.             this.showQuery = this.GetEntityQuery(new EntityQueryDesc
    101.             {
    102.                 None = this.hideTypes,
    103.                 All = new[] { ComponentType.ReadOnly<Hidden>() },
    104.             });
    105.         }
    106.  
    107.         /// <inheritdoc />
    108.         protected override void OnUpdate()
    109.         {
    110.             switch (this.mode)
    111.             {
    112.                 case HideMode.WorldBounds:
    113.                     this.HideEntitiesWorldBounds();
    114.                     this.ShowEntitiesWorldBounds();
    115.                     break;
    116.                 case HideMode.RenderMesh:
    117.                     this.HideEntitiesRenderMesh();
    118.                     this.ShowEntitiesRenderMesh();
    119.                     break;
    120.                 default:
    121.                     throw new ArgumentOutOfRangeException();
    122.             }
    123.         }
    124.  
    125.         private void HideEntitiesWorldBounds()
    126.         {
    127.             var chunks = this.hideQuery.CreateArchetypeChunkArray(Allocator.TempJob);
    128.  
    129.             var entityType = this.GetArchetypeChunkEntityType();
    130.             var renderBoundsType = this.GetArchetypeChunkComponentType<RenderBounds>();
    131.  
    132.             for (var chunkIndex = 0; chunkIndex < chunks.Length; chunkIndex++)
    133.             {
    134.                 var chunk = chunks[chunkIndex];
    135.  
    136.                 var renderBounds = chunk.GetNativeArray(renderBoundsType);
    137.  
    138.                 if (renderBounds.Length > 0)
    139.                 {
    140.                     for (var i = 0; i < chunk.Count; i++)
    141.                     {
    142.                         renderBounds[i] = new RenderBounds { Value = OutOfBounds };
    143.                     }
    144.                 }
    145.                 else
    146.                 {
    147.                     this.HideMeshRenderer(chunk, entityType, false);
    148.                 }
    149.             }
    150.  
    151.             chunks.Dispose();
    152.  
    153.             // Add hidden to the entire chunk
    154.             this.EntityManager.AddComponent(this.hideQuery, typeof(Hidden));
    155.         }
    156.  
    157.         private void HideEntitiesRenderMesh()
    158.         {
    159.             var chunks = this.hideQuery.CreateArchetypeChunkArray(Allocator.TempJob);
    160.  
    161.             var entityType = this.GetArchetypeChunkEntityType();
    162.             var renderMeshType = this.GetArchetypeChunkSharedComponentType<RenderMesh>();
    163.  
    164.             for (var chunkIndex = 0; chunkIndex < chunks.Length; chunkIndex++)
    165.             {
    166.                 var chunk = chunks[chunkIndex];
    167.  
    168.                 var renderMeshIndex = chunk.GetSharedComponentIndex(renderMeshType);
    169.                 var entities = chunk.GetNativeArray(entityType);
    170.  
    171.                 if (renderMeshIndex >= 0)
    172.                 {
    173.                     var renderMesh = this.EntityManager.GetSharedComponentData<RenderMesh>(renderMeshIndex);
    174.  
    175.                     if (!this.meshes.Forward.TryGetValue(renderMesh, out var index))
    176.                     {
    177.                         index = this.meshes[renderMesh] = ++this.meshIndex;
    178.                     }
    179.  
    180.                     for (var i = 0; i < chunk.Count; i++)
    181.                     {
    182.                         var entity = entities[i];
    183.  
    184.                         this.PostUpdateCommands.RemoveComponent<RenderMesh>(entity);
    185.                         this.PostUpdateCommands.AddComponent(entity, new Hidden { RenderMeshIndex = index });
    186.                     }
    187.                 }
    188.                 else
    189.                 {
    190.                     this.HideMeshRenderer(chunk, entityType, true);
    191.                 }
    192.             }
    193.  
    194.             chunks.Dispose();
    195.         }
    196.  
    197.         private void HideMeshRenderer(ArchetypeChunk chunk, ArchetypeChunkEntityType entityType, bool addHidden)
    198.         {
    199.             var entities = chunk.GetNativeArray(entityType);
    200.  
    201.             for (var i = 0; i < chunk.Count; i++)
    202.             {
    203.                 var entity = entities[i];
    204.  
    205.                 if (this.EntityManager.HasComponent<MeshRenderer>(entity))
    206.                 {
    207.                     this.EntityManager.GetComponentObject<MeshRenderer>(entity).enabled = false;
    208.                 }
    209.  
    210.                 if (addHidden)
    211.                 {
    212.                     this.PostUpdateCommands.AddComponent(entity, default(Hidden));
    213.                 }
    214.             }
    215.         }
    216.  
    217.         private void ShowEntitiesWorldBounds()
    218.         {
    219.             var chunks = this.showQuery.CreateArchetypeChunkArray(Allocator.TempJob);
    220.  
    221.             var entityType = this.GetArchetypeChunkEntityType();
    222.  
    223.             for (var chunkIndex = 0; chunkIndex < chunks.Length; chunkIndex++)
    224.             {
    225.                 var chunk = chunks[chunkIndex];
    226.                 var entities = chunk.GetNativeArray(entityType);
    227.  
    228.                 for (var i = 0; i < chunk.Count; i++)
    229.                 {
    230.                     var entity = entities[i];
    231.  
    232.                     if (this.EntityManager.HasComponent<MeshRenderer>(entity))
    233.                     {
    234.                         this.EntityManager.GetComponentObject<MeshRenderer>(entity).enabled = true;
    235.                     }
    236.                 }
    237.             }
    238.  
    239.             chunks.Dispose();
    240.  
    241.             this.EntityManager.RemoveComponent(this.showQuery, typeof(RenderBounds));
    242.             this.EntityManager.RemoveComponent(this.showQuery, typeof(Hidden));
    243.         }
    244.  
    245.         private void ShowEntitiesRenderMesh()
    246.         {
    247.             var chunks = this.showQuery.CreateArchetypeChunkArray(Allocator.TempJob);
    248.  
    249.             var entityType = this.GetArchetypeChunkEntityType();
    250.             var hiddenType = this.GetArchetypeChunkComponentType<Hidden>(true);
    251.  
    252.             for (var chunkIndex = 0; chunkIndex < chunks.Length; chunkIndex++)
    253.             {
    254.                 var chunk = chunks[chunkIndex];
    255.                 var entityArray = chunk.GetNativeArray(entityType);
    256.                 var hiddenArray = chunk.GetNativeArray(hiddenType);
    257.  
    258.                 for (var i = 0; i < chunk.Count; i++)
    259.                 {
    260.                     var entity = entityArray[i];
    261.  
    262.                     if (this.EntityManager.HasComponent<MeshRenderer>(entity))
    263.                     {
    264.                         this.EntityManager.GetComponentObject<MeshRenderer>(entity).enabled = true;
    265.                     }
    266.                     else
    267.                     {
    268.                         var hidden = hiddenArray[i];
    269.  
    270.                         if (hidden.RenderMeshIndex > 0)
    271.                         {
    272.                             this.PostUpdateCommands.AddSharedComponent(entity, this.meshes[hidden.RenderMeshIndex]);
    273.                         }
    274.                     }
    275.                 }
    276.             }
    277.  
    278.             chunks.Dispose();
    279.  
    280.             this.EntityManager.RemoveComponent(this.showQuery, typeof(Hidden));
    281.         }
    282.     }
    283. }
    It will just hide MeshRenderer by disabling/enabling it.
    While for pure entities using RenderMesh you have 2 choices on how they are hidden.

    Hide by RenderMesh - this will simply remove the RenderMesh from the component and store a copy of it. This is not ideal as RenderMesh is a CSD but if you only need to do this a couple of times/frame I've never noticed any real performance issues. Has benefit of removing entity from all render systems.

    Hide by WorldBounds - this will override the render bounds with bounds that will always be out of cull range therefore the render system will always cull the entity stopping it rendering. Does not have the cost of changing chunks but the entity is still processed by the render system. Also means you can no longer use WorldRenderBounds in your own systems and the data will be garbage.

    You can choose what components will hide an entity. For example, maybe you have a InFogOfWar component and a IsStealthed component. Pass those both into the system via hideTypes and if either are present the entity will be hidden.

    -edit-

    It has unit tests if that is something you like or want to extend it.

    Code (CSharp):
    1. // <copyright file="HiddenSystemTests.cs" company="BovineLabs">
    2. // Copyright (c) BovineLabs. All rights reserved.
    3. // </copyright>
    4.  
    5. namespace BovineLabs.Vision.Tests.Systems
    6. {
    7.     using BovineLabs.Common.Tests;
    8.     using BovineLabs.Vision.Components;
    9.     using BovineLabs.Vision.Systems;
    10.     using NUnit.Framework;
    11.     using Unity.Entities;
    12.     using Unity.Rendering;
    13.     using UnityEngine;
    14.     using Assert = UnityEngine.Assertions.Assert;
    15.  
    16.     /// <summary>
    17.     /// Tests for <see cref="HiddenSystem"/>.
    18.     /// </summary>
    19.     public class HiddenSystemTests : ECSTestsFixture
    20.     {
    21.         /// <summary>
    22.         /// Tests <see cref="Hidden"/> being added and removed.
    23.         /// </summary>
    24.         /// <param name="mode">The <see cref="HideMode"/>.</param>
    25.         [TestCase(HideMode.RenderMesh)]
    26.         [TestCase(HideMode.WorldBounds)]
    27.         public void HideToggleAddsRemovesHidden(HideMode mode)
    28.         {
    29.             var system = this.World.AddSystem(new HiddenSystem(mode, typeof(TestHide)));
    30.             var entity = this.m_Manager.CreateEntity(typeof(TestHide));
    31.  
    32.             system.Update();
    33.             this.CompleteAllJobs();
    34.  
    35.             Assert.IsTrue(this.m_Manager.HasComponent<Hidden>(entity));
    36.  
    37.             this.m_Manager.RemoveComponent<TestHide>(entity);
    38.  
    39.             system.Update();
    40.             this.CompleteAllJobs();
    41.  
    42.             Assert.IsFalse(this.m_Manager.HasComponent<Hidden>(entity));
    43.         }
    44.  
    45.         /// <summary>
    46.         /// Tests <see cref="RenderBounds"/> being set in <see cref="HideMode.WorldBounds"/>.
    47.         /// </summary>
    48.         [Test]
    49.         public void ModeWorldBoundsSetsRemovesRenderBounds()
    50.         {
    51.             var system = this.World.AddSystem(new HiddenSystem(HideMode.WorldBounds, typeof(TestHide)));
    52.             var entity = this.m_Manager.CreateEntity(
    53.                 typeof(TestHide),
    54.                 typeof(RenderBounds));
    55.  
    56.             Assert.AreNotEqual(
    57.                 HiddenSystem.OutOfBounds,
    58.                 this.m_Manager.GetComponentData<RenderBounds>(entity).Value);
    59.  
    60.             system.Update();
    61.             this.CompleteAllJobs();
    62.  
    63.             Assert.AreEqual(
    64.                 HiddenSystem.OutOfBounds,
    65.                 this.m_Manager.GetComponentData<RenderBounds>(entity).Value);
    66.  
    67.             this.m_Manager.RemoveComponent<TestHide>(entity);
    68.  
    69.             system.Update();
    70.             this.CompleteAllJobs();
    71.  
    72.             Assert.IsFalse(this.m_Manager.HasComponent<RenderBounds>(entity));
    73.         }
    74.  
    75.         /// <summary>
    76.         /// Tests <see cref="RenderMesh"/> being set in <see cref="HideMode.RenderMesh"/>.
    77.         /// </summary>
    78.         [Test]
    79.         public void ModeRenderMeshRemovesAddsRenderMesh()
    80.         {
    81.             var system = this.World.AddSystem(new HiddenSystem(HideMode.RenderMesh, typeof(TestHide)));
    82.             var entity = this.m_Manager.CreateEntity(
    83.                 typeof(TestHide),
    84.                 typeof(RenderMesh));
    85.  
    86.             var renderMesh = new RenderMesh
    87.             {
    88.                 // just non default value
    89.                 receiveShadows = true,
    90.             };
    91.  
    92.             this.m_Manager.SetSharedComponentData(entity, renderMesh);
    93.  
    94.             system.Update();
    95.             this.CompleteAllJobs();
    96.  
    97.             Assert.IsFalse(this.m_Manager.HasComponent<RenderMesh>(entity));
    98.  
    99.             this.m_Manager.RemoveComponent<TestHide>(entity);
    100.  
    101.             system.Update();
    102.             this.CompleteAllJobs();
    103.  
    104.             Assert.IsTrue(this.m_Manager.HasComponent<RenderMesh>(entity));
    105.  
    106.             Assert.AreEqual(renderMesh, this.m_Manager.GetSharedComponentData<RenderMesh>(entity));
    107.         }
    108.  
    109.         /// <summary>
    110.         /// Tests <see cref="MeshRenderer"/> being toggled.
    111.         /// </summary>
    112.         /// <param name="mode">The <see cref="HideMode"/>.</param>
    113.         [TestCase(HideMode.RenderMesh)]
    114.         [TestCase(HideMode.WorldBounds)]
    115.         public void HideToggleDisablesEnablesMeshRenderer(HideMode mode)
    116.         {
    117.             var system = this.World.AddSystem(new HiddenSystem(mode, typeof(TestHide)));
    118.             var entity = this.m_Manager.CreateEntity(typeof(TestHide));
    119.             var meshRenderer = new GameObject().AddComponent<MeshRenderer>();
    120.             this.m_Manager.AddComponentObject(entity, meshRenderer);
    121.  
    122.             Assert.IsTrue(this.m_Manager.GetComponentObject<MeshRenderer>(entity).enabled);
    123.  
    124.             system.Update();
    125.             this.CompleteAllJobs();
    126.  
    127.             Assert.IsFalse(this.m_Manager.GetComponentObject<MeshRenderer>(entity).enabled);
    128.  
    129.             this.m_Manager.RemoveComponent<TestHide>(entity);
    130.  
    131.             system.Update();
    132.             this.CompleteAllJobs();
    133.  
    134.             Assert.IsTrue(this.m_Manager.GetComponentObject<MeshRenderer>(entity).enabled);
    135.         }
    136.  
    137.         /// <summary>
    138.         /// Tests any hide type sets hidden in <see cref="HideMode.WorldBounds"/>.
    139.         /// </summary>
    140.         /// <param name="mode">The <see cref="HideMode"/>.</param>
    141.         [TestCase(HideMode.RenderMesh)]
    142.         [TestCase(HideMode.WorldBounds)]
    143.         public void AnyHideShouldSetHidden(HideMode mode)
    144.         {
    145.             var hiddenSystem = this.World.AddSystem(new HiddenSystem(mode, typeof(TestHide), typeof(TestHide2)));
    146.             var entity = this.m_Manager.CreateEntity(typeof(TestHide2));
    147.             var entity2 = this.m_Manager.CreateEntity(typeof(TestHide));
    148.  
    149.             hiddenSystem.Update();
    150.             this.CompleteAllJobs();
    151.  
    152.             Assert.IsTrue(this.m_Manager.HasComponent<Hidden>(entity));
    153.             Assert.IsTrue(this.m_Manager.HasComponent<Hidden>(entity2));
    154.         }
    155.  
    156.         /// <summary>
    157.         /// Tests removing one hide keeps hidden in <see cref="HideMode.WorldBounds"/>.
    158.         /// </summary>
    159.         /// <param name="mode">The <see cref="HideMode"/>.</param>
    160.         [TestCase(HideMode.RenderMesh)]
    161.         [TestCase(HideMode.WorldBounds)]
    162.         public void ModeWorldBoundsRemovingHideWhenAnotherHideStaysHidden(HideMode mode)
    163.         {
    164.             var hiddenSystem = this.World.AddSystem(new HiddenSystem(mode, typeof(TestHide), typeof(TestHide2)));
    165.             var entity = this.m_Manager.CreateEntity(typeof(TestHide), typeof(TestHide2), typeof(Hidden));
    166.  
    167.             this.m_Manager.RemoveComponent<TestHide>(entity);
    168.  
    169.             hiddenSystem.Update();
    170.             this.CompleteAllJobs();
    171.  
    172.             Assert.IsTrue(this.m_Manager.HasComponent<Hidden>(entity));
    173.         }
    174.  
    175.         private struct TestHide2 : IComponentData
    176.         {
    177.         }
    178.  
    179.         private struct TestHide : IComponentData
    180.         {
    181.         }
    182.     }
    183. }
    Note this code is missing a few dependencies so won't compile as is but you should be able to replace easy enough but I might look to see if I can separate them if there is interest.

    Also side note, I'm using this is an upcoming vision system I'm working on!

     
    Last edited: May 29, 2019
    cj-currie, jmcusack, Lontis and 6 others like this.
  6. ParametrixFX

    ParametrixFX

    Joined:
    Nov 14, 2018
    Posts:
    18
    @tertle: Thanks for sharing. Your code looks very promising.

    I'm trying to avoid adding/removing components because I want everything to be done from a job. Beside, removing mesh component also has a draw back of needing to store it for that entity.

    So, I think setting worldbound is the best idea. However I have a question with your system: In HideEntitiesWorldBounds() you set the WorldBound value to "invalid" value, but you never set it back to a "valid" value in ShowEntitiesWorldBounds(). I'm just confusing on how this works.
     
  7. Opeth001

    Opeth001

    Joined:
    Jan 28, 2017
    Posts:
    1,117
    @samlytle can you tell us what are you aiming for ? maybe we can get better ideas having more details about what you exactly need to do.
    in my game i was aiming for culling rendering and physics so i ended up by divinding my MAP into litle regions of 50m²
    and then i added a SCD to all my Environment Entities specifying values in conversion workflow, then each time my player changes region i move all entities containing regions values out of interest to another world ( a caching world not affected by any default system ), moving them is done by chunks not individual entities. so it's soooo Fast.
    in this way im not adding/removing/modifying any component within my entities and everything is parallalized.
     
  8. ParametrixFX

    ParametrixFX

    Joined:
    Nov 14, 2018
    Posts:
    18
    @Opeth001, essentially we are developing a simulated traffic system. We are aiming to have 10.000 vehicles showing on screen at once. Our physical world is really big (a city section). For each vehicle, there are 1 body entity and 4 wheel entities (we separated them in order to make the wheel rotates). Our vehicles are moving on a spline. What we want is to hide the vehicles when they reach to the end of the spline and to be respawned later at the start of the spline.
    There are a lot of entities to be managed since hiding 1 body also means hiding its 4 wheels. That's why we assumed adding/removing is not the best idea.
     
  9. Opeth001

    Opeth001

    Joined:
    Jan 28, 2017
    Posts:
    1,117
    @samlytle
    are yo having performance issues rendering 10k vehicules and 40k wheels bursted ?
     
  10. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,775
    I am sure, that should not be an issue. Unless on mobile?

    The easiest way, is to put mesh, far away outside camera frustum. Like for example 100k, or even further, where camera don't see. Or below the terrain.
    Many games used that techniques in the past and still uses.
     
    ParametrixFX likes this.
  11. ParametrixFX

    ParametrixFX

    Joined:
    Nov 14, 2018
    Posts:
    18
    @Opeth001 No. rendering is not an issue because our vehicles are not very high poly.
    @Antypodish Cool.
     
  12. Opeth001

    Opeth001

    Joined:
    Jan 28, 2017
    Posts:
    1,117
    I think even for mobile 10k vehicules should not overhead the CPU.
    but there's something im not understanding about the HybredRendererSystemV2, performance is affected by all kinds of entities even if they dont have the RendererMesh Component.
    Example Here.
     
  13. Opeth001

    Opeth001

    Joined:
    Jan 28, 2017
    Posts:
    1,117
    @samlytle im not getting why you dont want disable the entities reaching to the end of the spline.
    maybe if you have custom logic on hiden entities,

    1) Create entities containing the data needed from cars that need to be hidden.
    2) Disable hidden Cars.
    3) Process entities Holding the Data for hidden Cars.
    4) Copy Data From entities temporary entities to Cars and destroy them.
    5) Enable hidden Cars.

    creating and destroying entities is not a heavy thing to do this is why ECS is Awesome
     
  14. ParametrixFX

    ParametrixFX

    Joined:
    Nov 14, 2018
    Posts:
    18
    Opeth001 likes this.
  15. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,761
    I remove it

    Code (CSharp):
    1. this.EntityManager.RemoveComponent(this.showQuery, typeof(RenderBounds));
    which lets the the unity rendering systems recalculate it. This way if the mesh it's generated off changes while hidden it'll be updated correctly vs if I stored the value beforehand.
     
    ParametrixFX likes this.
  16. ParametrixFX

    ParametrixFX

    Joined:
    Nov 14, 2018
    Posts:
    18
    I have implemented the re-locating entities strategy. I think it would be best this way since we can move them inside a job. So we don't need to maintain a sync point. Thank everyone for your help!
     
    Antypodish and Opeth001 like this.
  17. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,761
    It's definitely the more performant approach however I no longer use it as I use WorldRenderBounds to perform culling for logic (certain systems update less often off screen). Glad it helped though.