Search Unity

BUG: GetComponentGroup with EntityArchetypeQuery doesn't add dependencies and can never create group

Discussion in 'Entity Component System' started by iam2bam, Dec 22, 2018.

  1. iam2bam

    iam2bam

    Joined:
    Mar 9, 2016
    Posts:
    36
    GetComponentGroup with EntityArchetypeQuery doesn't add "AddReaderWriter" dependencies and specific CompareQuery (in EntityGroupManager) has wrong predicate making impossible to create a group through an archetype query.

    A change in call order could also affect component type dependency because once registered in m_ComponentGroups, the group is just returned from that array, never again calling AddReaderWriter as it does when GetComponentGroup is called with a ComponentType[].
    Difference lays in GetComponentGroupInternal (depending on parameter type)

    Traced it to EntityGroupManager.cs, notice for EntityArchetypeQuery checks inequality, while for ComponentType checks equality to null
    EDIT: Upon further investigation, the next code is correct (mismatching by signature), and the problem is that the feature is missing making the API is asymmetric.
    So I guess I must do GetComponentGroup with a ComponentType[] of the "All" subset first to set the data dependency of the system, and then iterate by chunks by archetype query that allow me to filter by Any.

    Code (CSharp):
    1.         public static bool CompareQuery(EntityArchetypeQuery[] query, EntityGroupData* groupData)
    2.         {
    3.             if (groupData->RequiredComponents != null)
    4.                 return false;
    5.  
    6.  
    7.  
    8.         public static bool CompareComponents(ComponentType[] componentTypes, EntityGroupData* groupData)
    9.         {
    10.             if (groupData->RequiredComponents == null)
    11.                 return false;
    Entities version 0.0.12-preview.21
     
    Last edited: Dec 22, 2018
  2. julian-moschuering

    julian-moschuering

    Joined:
    Apr 15, 2014
    Posts:
    529
    AddReaderWriter for queries is executed in the GetArchetype*Type functions as the query itself is only a filter to select the archetypes and does not necessarily mean that you require read or write access to any of the components.
     
  3. iam2bam

    iam2bam

    Joined:
    Mar 9, 2016
    Posts:
    36
    API asymmetry for a function with the same name (GetComponentGroup) doesn't make sense and it's indefensible.
    They should both or none AddReadWriter.
    Also calling both function signatures in different order will make only one fail, or both fail.

    Besides that, there's a bug inside the official code not allowing EntityArchetypeQuery to work.

    Test case:
    Code (CSharp):
    1. using System;
    2. using Unity.Entities;
    3. using UnityEngine;
    4.  
    5. public struct Data : IComponentData {
    6.     public int number;
    7. }
    8.  
    9. public class BugSystem : ComponentSystem {
    10.     protected override void OnCreateManager() {
    11.         var types = new ComponentType[] { typeof(Data) };
    12.         var ent = EntityManager.CreateEntity(types);
    13.         EntityManager.SetComponentData(ent, new Data { number = 42 });
    14.  
    15.         //WORKS
    16.         var group = GetComponentGroup(types);
    17.         var array = group.GetComponentDataArray<Data>();
    18.  
    19.         //FAILS
    20.         var query = new EntityArchetypeQuery {
    21.             Any = Array.Empty<ComponentType>()
    22.             , None = Array.Empty<ComponentType>()
    23.             , All = types
    24.         };
    25.         group = GetComponentGroup(query);
    26.         array = group.GetComponentDataArray<Data>(); //<-- throws:
    27.                                                      //InvalidOperationException: Trying to get iterator for Data but the required component type was not declared in the EntityGroup.
    28.     }
    29.  
    30.     protected override void OnUpdate() {
    31.  
    32.     }
    33. }
     
  4. julian-moschuering

    julian-moschuering

    Joined:
    Apr 15, 2014
    Posts:
    529
    Yes, the ComponentGroup api should probably get split into chunk iteration and direct component iteration to prevent the incorrect usage or both should be supported with both query methods.

    When using ArchetypeQueries you do chunk iteration which means you have to call GetArchetypeChunkArray not GetComponentDataArray. I don't know what the plans are, maybe GetComppnentDataArray will get supported in the future.
     
  5. iam2bam

    iam2bam

    Joined:
    Mar 9, 2016
    Posts:
    36
    I wasn't aware of that, thanks. I've been stepping into more thoroughly and came to the same conclusion finding this happy TODO...

    Code (CSharp):
    1.         public ComponentGroup CreateEntityGroup(ArchetypeManager typeMan, EntityDataManager* entityDataManager, EntityArchetypeQuery[] query)
    2.         {
    3.             //@TODO: Support for CreateEntityGroup with query but using ComponentDataArray etc
    4.             return CreateEntityGroup(typeMan, entityDataManager, CreateQuery(query), query.Length, null, 0);
    5.         }
    Anyway, should be documented if it's WIP. And by documented I mean at least different function names for different behaviors... Could set some internal check flag to warn according how it was built, too.