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

Best approach for disabling Entities by Region

Discussion in 'Entity Component System' started by Opeth001, Mar 20, 2020.

  1. Opeth001

    Opeth001

    Joined:
    Jan 28, 2017
    Posts:
    1,078
    Hello Everyone,

    me and some friends are making a TOP-DOWN game style with a big World Map ( arround 300k Entities and 1.4 km² ), it's big enough to create unstable framerate on med-end devices.

    im trying to optimize the Hybred Renderering and Physics calculations by manually disabling Chunks that are too far from camera.

    the solution i found is deviding all entities by adding a ChunkComponentData CCD "Region" in a way that i can Enable/Disable all chunks in Bursted Jobs.

    eg: in this case only chunks with CCD (8,9,10,14,15,16,20,21,22) will be enabled.


    what would be the most efficient way to select all chunks having CCD with values (8,9,10,14,15,16,20,21,22) ?

    Note:
    * visible Regions can be up to 9 visible regions simultaneously.
    * this system will run only when the camera itself switches Region.
    * this system will be applied to all chunks having the ( ChunkWorldRenderBounds CCD or PhysicsCollider CD ) + RegionID CCD.
     
    Last edited: Mar 21, 2020
    Mikael-H likes this.
  2. SurprisedPikachu

    SurprisedPikachu

    Joined:
    Mar 12, 2020
    Posts:
    84
    I have not tried it myself, but you can create a ISharedComponentData called "RegionID" to hold the region where that entity is currently in. You should give this to all of your entities in the world.
    Then when you want to render (or anything really. You can even cull logic here), you filter your query by "RegionID" shared component.
     
    Opeth001 likes this.
  3. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    5,203
    Using RegionID shared component is the right approach. Given that you simply want to enable / disable based on those regions. Simplest & highly optimzied codepath is to simply:

    Make a query with RegionID, filter it to the specific region. And then EntityManager.AddComponent/Removecomponent<Disabled>(query);

    To enable / disable all entities in that region..

    Query based AddComponent/RemoveComponent takes advantage that all entities are already in a chunk and that the data layout is the same, so its basically just assigning an archetype per chunk. It is very fast to do that for even thousands of entities.
     
  4. Opeth001

    Opeth001

    Joined:
    Jan 28, 2017
    Posts:
    1,078
    are you guys planning to add some kind of Filtring queries Like dotnet's LINQ queries Feature ?
    EG:
    Code (CSharp):
    1.  
    2.     EntityQuery m_RegionsToDisable;
    3.  
    4.     protected override void OnCreate()
    5.     {
    6.         base.OnCreate();
    7.  
    8.         m_RegionsToDisable = GetEntityQuery(ComponentType.ReadOnly(typeof(WorldMapRegion)));
    9.     }
    10.  
    11.     protected override void OnUpdate()
    12.     {
    13.         m_RegionsToDisable.SetSharedComponentFilter<SCD_Type>(scd => { scd.X >= -1 && scd.X <= 1 && scd.Y >= 2 && scd.Y <= 4  });
    14.  

     
    Last edited: Apr 29, 2020
  5. agurskis22cans

    agurskis22cans

    Joined:
    Jul 17, 2019
    Posts:
    9
    Doesn't the use of EntityManager create a sync point, and we want to avoid sync points? Can you do query changes to the components using entity command buffer? or am I missing a point?
     
    Opeth001 likes this.