Search Unity

EntityQuery Filter a SCD with Multiple Values

Discussion in 'Entity Component System' started by Opeth001, Jun 23, 2019.

  1. Opeth001

    Opeth001

    Joined:
    Jan 28, 2017
    Posts:
    1,117
    is there any way to use The EntityQuery and filter it using multiple values of the Same SCD ?

    eg:
    m_Group.SetMultipleFilter( new SharedComponent[] {
    new SharedComponent { Value = Value1},
    new SharedComponent { Value = Value2},
    new SharedComponent { Value = Value3},
    new SharedComponent { Value = Value4})

    or maybe a combining multiple filtred Queries.

    im trying to move entities between two Worlds using multiple EntityQuerys and by calling the function "MoveEntitiesFrom" multiple times, the GC is suffering.
     
  2. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    1,555
    I remembered SCD filter supports up to 2 different value at the same time. More than that you may need a custom IJobChunk (where you remember as many SCD indexes as you want to, then while iterating chunks you skip (or inversely do something) on chunks without/with one of those indexes.

    But MoveEntitiesFrom use EQ so that's not applicable. What I did in my game is kinda hacky but good enough : use the filter one by one on the EQ and use EntityManager.AddComponent(eq) while each filter is active to tag the chunk with tag component called MoveStaging. This should cost virtually nothing since it is a chunk operation and tag component do not require chunk data rearrange. Then you make a new EQ with just that tag component and use it with MoveEntitiesFrom. The method will receive all chunks you "staged". In the other world remove all staging tags at once with EntityManager, again should cost virtually nothing.
     
    eizenhorn likes this.
  3. Opeth001

    Opeth001

    Joined:
    Jan 28, 2017
    Posts:
    1,117
    Oh thank you 5argon you saved my day again ^_^!
     
  4. Opeth001

    Opeth001

    Joined:
    Jan 28, 2017
    Posts:
    1,117
    @5argon
    i Added CD Tag "DisabledWorldMapRegion" to All my Entities that need to be Moved to the Caching world and then i just remove this Tag when i want to port it back the MainWorld. calling EntityManager.MoveEntitiesFrom(), is blocking the execution with this Error:


    ArgumentException: The entity does not exist
    Unity.Entities.EntityComponentStore.AssertEntityHasComponent (Unity.Entities.Entity entity, Unity.Entities.ComponentType componentType) (at Library/PackageCache/com.unity.entities@0.0.12-preview.33/Unity.Entities/EntityComponentStore.cs:486)
    Unity.Entities.EntityComponentStore.AssertEntityHasComponent (Unity.Entities.Entity entity, System.Int32 componentType) (at Library/PackageCache/com.unity.entities@0.0.12-preview.33/Unity.Entities/EntityComponentStore.cs:494)
    Unity.Entities.ComponentDataFromEntity`1[T].get_Item (Unity.Entities.Entity entity) (at Library/PackageCache/com.unity.entities@0.0.12-preview.33/Unity.Entities/Iterators/ComponentDataFromEntity.cs:116)
    Unity.Transforms.LocalToParentSystem+UpdateHierarchy.ChildLocalToWorld (Unity.Mathematics.float4x4 parentLocalToWorld, Unity.Entities.Entity entity) (at Library/PackageCache/com.unity.entities@0.0.12-preview.33/Unity.Transforms/LocalToParentSystem.cs:29)
    Unity.Transforms.LocalToParentSystem+UpdateHierarchy.ChildLocalToWorld (Unity.Mathematics.float4x4 parentLocalToWorld, Unity.Entities.Entity entity) (at Library/PackageCache/com.unity.entities@0.0.12-preview.33/Unity.Transforms/LocalToParentSystem.cs:38)
    Unity.Transforms.LocalToParentSystem+UpdateHierarchy.Execute (Unity.Entities.ArchetypeChunk chunk, System.Int32 index, System.Int32 entityOffset) (at Library/PackageCache/com.unity.entities@0.0.12-preview.33/Unity.Transforms/LocalToParentSystem.cs:53)
    Unity.Entities.JobChunkExtensions+JobChunk_Process`1[T].ExecuteInternal (Unity.Entities.JobChunkExtensions+JobChunkData`1[T]& jobData, Unity.Jobs.LowLevel.Unsafe.JobRanges& ranges, System.Int32 jobIndex) (at Library/PackageCache/com.unity.entities@0.0.12-preview.33/Unity.Entities/IJobChunk.cs:135)
    Unity.Entities.JobChunkExtensions+JobChunk_Process`1[T].Execute (Unity.Entities.JobChunkExtensions+JobChunkData`1[T]& jobData, System.IntPtr additionalPtr, System.IntPtr bufferRangePatchData, Unity.Jobs.LowLevel.Unsafe.JobRanges& ranges, System.Int32 jobIndex) (at Library/PackageCache/com.unity.entities@0.0.12-preview.33/Unity.Entities/IJobChunk.cs:122)



    my systems :

    WorldsRegionsPicker : Select All Regions that need to be shown by the local player depending his position.

    WorldsRegionsTagger :
    1) Tag with "DisabledWorldMapRegion" All chunks Within the MainWorld that need to be cached depending on their "WorldMapRegion" SCD.
    2) Remove "DisabledWorldMapRegion" Tag from All chunks Within the CachingWorld that need to be shown to the local player.

    WorldsRegionsMover : Move all Chunks Tagged with "DisabledWorldMapRegion" From the Main World to the Caching World and Move back all Chunks not Contining the Tag From the Caching World to the Main World.
     
  5. Opeth001

    Opeth001

    Joined:
    Jan 28, 2017
    Posts:
    1,117
    it seems like Moving entities from a world to another by using the EntityManager.MoveEntitiesFrom function is not automatically handling entities Childs.
    so i tagged all childs recursively within parents and everything is working.
    also disabling entities doesn't disable childs which is pretty strange knowing that the TransformSystemGroup is supposed to imitate Gameobjects hierarchy workflow.
     
    5argon likes this.
  6. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    1,555
    Opeth001 likes this.
  7. Opeth001

    Opeth001

    Joined:
    Jan 28, 2017
    Posts:
    1,117
    @5argon
    Did you found a good solution for disabling entities and childs ?
    my "WorldsRegionsDisabler" Is having an error when trying to tag a Child while it's parent is disabled.

    Code (CSharp):
    1.  
    2.     [UpdateInGroup(typeof(SimulationSystemGroup))]
    3.     [UpdateAfter(typeof(WorldsRegionsPicker))]
    4.     public class WorldsRegionsDisabler : ComponentSystem
    5.     {
    6.         EntityQuery regionsToCache;
    7.         EntityQuery regionsToLoad;
    8.  
    9.         EntityQuery query_EnabledRegions;
    10.         EntityQuery query_DisabledRegions;
    11.  
    12.         // Queries to Enable/Disable Entities and Childs recursively
    13.         EntityQuery query_EntitiesToEnableWithChilds;
    14.         EntityQuery query_EntitiesToEnableWithoutChilds;
    15.  
    16.         EntityQuery query_EntitiesToDisableWithChilds;
    17.         EntityQuery query_EntitiesToDisableWithoutChilds;
    18.  
    19.         protected override void OnCreateManager()
    20.         {
    21.             regionsToCache = GetEntityQuery(ComponentType.ReadOnly(typeof(RegionToCache)));
    22.             regionsToLoad = GetEntityQuery(ComponentType.ReadOnly(typeof(RegionToLoad)));
    23.  
    24.  
    25.             query_EnabledRegions = GetEntityQuery(ComponentType.ReadOnly(typeof(WorldMapRegion)));
    26.             query_DisabledRegions = GetEntityQuery(ComponentType.ReadOnly(typeof(WorldMapRegion)), ComponentType.ReadOnly(typeof(Disabled)));
    27.  
    28.  
    29.     //  To Enable
    30.             // Query for Entities to Enable + having Childs
    31.             query_EntitiesToEnableWithChilds = GetEntityQuery(ComponentType.ReadOnly(typeof(LinkedEntityGroup)), ComponentType.ReadOnly(typeof(EntityToEnable)), ComponentType.ReadOnly(typeof(Disabled)));
    32.  
    33.  
    34.             // Query for Entities to Enable whithout Childs
    35.             var toEnableWithoutChild = new EntityQueryDesc
    36.             {
    37.                 All = new ComponentType[] {  ComponentType.ReadOnly(typeof(EntityToEnable)), ComponentType.ReadOnly(typeof(Disabled)) },
    38.                 None = new ComponentType[] { ComponentType.ReadOnly(typeof(LinkedEntityGroup)) }
    39.             };
    40.             query_EntitiesToEnableWithoutChilds = GetEntityQuery(toEnableWithoutChild);
    41.  
    42.     //  To Disable
    43.             // Query for Entities to Disable + having Childs
    44.             query_EntitiesToDisableWithChilds = GetEntityQuery(ComponentType.ReadOnly(typeof(LinkedEntityGroup)), ComponentType.ReadOnly(typeof(EntityToDisable)));
    45.  
    46.  
    47.             // Query for Entities to Disable whithout Childs
    48.             var toDisableWithoutChild = new EntityQueryDesc
    49.             {
    50.                 All = new ComponentType[] { ComponentType.ReadOnly(typeof(EntityToDisable)) },
    51.                 None = new ComponentType[] { ComponentType.ReadOnly(typeof(LinkedEntityGroup)) }
    52.             };
    53.             query_EntitiesToDisableWithoutChilds = GetEntityQuery(toDisableWithoutChild);
    54.  
    55.  
    56.         }
    57.  
    58.  
    59.         protected override void OnUpdate( )
    60.         {
    61.  
    62.             var regionsToLoadCount = regionsToLoad.CalculateLength();
    63.  
    64.             var regionsToCacheCount = regionsToCache.CalculateLength();
    65.  
    66.  
    67.             #region Tagging Entities Within WorldMapRegion Commands
    68.  
    69.        
    70.            if (regionsToCacheCount > 0 )
    71.             {   // Normal Caching Workflow
    72.            
    73.                 var regionstoCacheIndexes = regionsToCache.ToComponentDataArray<RegionToCache>(Allocator.TempJob);
    74.  
    75.                 Debug.Log($"Regions to unload : {regionstoCacheIndexes.Length}");
    76.  
    77.  
    78.                 // Filter and Tag for desired entities within the Enabled Regions
    79.                 for (var i = 0; i < regionsToCacheCount; i++)
    80.                 {
    81.                     // Filter
    82.                     query_EnabledRegions.SetFilter(new WorldMapRegion { value = regionstoCacheIndexes[i].region });
    83.  
    84.                     // Add Tag
    85.                     if (query_EnabledRegions.CalculateLength() > 0)
    86.                         EntityManager.AddComponent(query_EnabledRegions, typeof(EntityToDisable));
    87.  
    88.                     // Reset Filter
    89.                     query_EnabledRegions.ResetFilter();
    90.                 }
    91.                 regionstoCacheIndexes.Dispose();
    92.  
    93.                 // Clear Loading Commands
    94.                 EntityManager.DestroyEntity(regionsToCache);
    95.             }
    96.      
    97.  
    98.  
    99.             // Need to Load Regions
    100.  
    101.             if (regionsToLoadCount > 0)
    102.             {
    103.                 var regionstoLoadIndexes = regionsToLoad.ToComponentDataArray<RegionToLoad>(Allocator.TempJob);
    104.                 Debug.Log($"Regions to Load : {regionstoLoadIndexes.Length}");
    105.            
    106.                 // Filter and Tag for desired entities within the disabled Regions
    107.                 for (var i = 0; i < regionsToLoadCount; i++)
    108.                 {
    109.                     // Filter
    110.                     query_DisabledRegions.SetFilter(new WorldMapRegion { value = regionstoLoadIndexes[i].region });
    111.  
    112.                     // Remove Tag
    113.                     if (query_DisabledRegions.CalculateLength() > 0)
    114.                         EntityManager.RemoveComponent(query_DisabledRegions, typeof(EntityToEnable));
    115.  
    116.                     // Reset Filter
    117.                     query_DisabledRegions.ResetFilter();
    118.                 }
    119.  
    120.                 regionstoLoadIndexes.Dispose();
    121.  
    122.                 // Clear Loading Commands
    123.                 EntityManager.DestroyEntity(regionsToLoad);
    124.             }
    125.  
    126.  
    127.  
    128.             #endregion
    129.  
    130.  
    131.  
    132.  
    133.             #region Disabling/Enabling Entities and Tagging childs
    134.  
    135.             // Enable Entities without Childs
    136.  
    137.             var _entitiesWithoutChildsToEnableCount = query_EntitiesToEnableWithoutChilds.CalculateLength();
    138.  
    139.             if(_entitiesWithoutChildsToEnableCount > 0)
    140.             {
    141.                 EntityManager.RemoveComponent(query_EntitiesToEnableWithoutChilds, typeof(EntityToEnable));
    142.                 EntityManager.RemoveComponent(query_EntitiesToEnableWithoutChilds, typeof(Disabled));
    143.             }
    144.  
    145.  
    146.  
    147.             // Disable Entities without Childs
    148.  
    149.             var _entitiesWithoutChildsToDisableCount = query_EntitiesToDisableWithoutChilds.CalculateLength();
    150.  
    151.             if (_entitiesWithoutChildsToDisableCount > 0)
    152.             {
    153.                 EntityManager.RemoveComponent(query_EntitiesToDisableWithoutChilds, typeof(EntityToDisable));
    154.                 EntityManager.AddComponent(query_EntitiesToDisableWithoutChilds, typeof(Disabled));
    155.             }
    156.  
    157.  
    158.  
    159.  
    160.  
    161.             // Enable Entities with Childs
    162.  
    163.             var _entitiesToEnableWithChildsCount = query_EntitiesToEnableWithChilds.CalculateLength();
    164.  
    165.             if (_entitiesToEnableWithChildsCount > 0)
    166.             {
    167.  
    168.  
    169.                 var ParentsToEnableArray = query_EntitiesToEnableWithChilds.ToEntityArray(Allocator.TempJob);
    170.  
    171.  
    172.                 for (var i = 0; i < ParentsToEnableArray.Length; i++)
    173.                 {
    174.                     var childsBuffer = EntityManager.GetBuffer<LinkedEntityGroup>(ParentsToEnableArray[i]);
    175.  
    176.                     if(childsBuffer.Length > 0)
    177.                     {
    178.                         var childsEntities = new NativeArray<Entity>(childsBuffer.Length,Allocator.TempJob);
    179.  
    180.                         // Adding Childs Entities to an Array
    181.                         for (var j = 0; j < childsBuffer.Length; j++)
    182.                             childsEntities[j] = childsBuffer[i].Value;
    183.  
    184.                         // Deffer Childs Enabling to the Next frame
    185.                         EntityManager.AddComponent(childsEntities, typeof(EntityToEnable));
    186.                         childsEntities.Dispose();
    187.                     }
    188.                
    189.                 }
    190.              
    191.                 ParentsToEnableArray.Dispose();
    192.  
    193.                 EntityManager.RemoveComponent(query_EntitiesToEnableWithChilds, typeof(EntityToEnable));
    194.                 EntityManager.RemoveComponent(query_EntitiesToEnableWithChilds, typeof(Disabled));
    195.             }
    196.  
    197.  
    198.  
    199.  
    200.  
    201.  
    202.  
    203.             // Disable Entities with Childs
    204.  
    205.             var _entitiesToDisableWithChildsCount = query_EntitiesToDisableWithChilds.CalculateLength();
    206.  
    207.             if (_entitiesToDisableWithChildsCount > 0)
    208.             {
    209.  
    210.  
    211.                 var ParentsToDisableArray = query_EntitiesToDisableWithChilds.ToEntityArray(Allocator.TempJob);
    212.  
    213.                 for (var i = 0; i < ParentsToDisableArray.Length; i++)
    214.                 {
    215.                     var childsBuffer = EntityManager.GetBuffer<LinkedEntityGroup>(ParentsToDisableArray[i]);
    216.  
    217.                     if (childsBuffer.Length > 0)
    218.                     {
    219.                         var childsEntities = new NativeArray<Entity>(childsBuffer.Length, Allocator.TempJob);
    220.  
    221.                         // Adding Childs Entities to an Array
    222.                         for (var j = 0; j < childsBuffer.Length; j++)
    223.                             childsEntities[j] = childsBuffer[i].Value;
    224.  
    225.                         // Deffer Childs Enabling to the Next frame
    226.                         EntityManager.AddComponent(childsEntities, typeof(EntityToDisable));
    227.                         childsEntities.Dispose();
    228.                     }
    229.  
    230.                 }
    231.  
    232.  
    233.                 ParentsToDisableArray.Dispose();
    234.  
    235.                 EntityManager.RemoveComponent(query_EntitiesToDisableWithChilds, typeof(EntityToDisable));
    236.                 EntityManager.AddComponent(query_EntitiesToDisableWithChilds, typeof(Disabled));
    237.  
    238.             }
    239.  
    240.             #endregion
    241.          
    242.         }
    243.     }
    244.  
    245.  
    246.  
    247.  
    EDIT:
    The Error is Throwing at line 226

    EDIT 2:
    im not getting errors when i remove the StaticOptimizeEntity from my regions
     
    Last edited: Jul 7, 2019