Search Unity

  1. We are migrating the Unity Forums to Unity Discussions. On July 12, the Unity Forums will become read-only. On July 15, Unity Discussions will become read-only until July 18, when the new design and the migrated forum contents will go live. Read our full announcement for more information and let us know if you have any questions.

Question Querying for entities after using AddComponent in the same OnUpdate call

Discussion in 'Entity Component System' started by DanOtt, Aug 6, 2022.

  1. DanOtt

    DanOtt

    Joined:
    Nov 4, 2019
    Posts:
    9
    EDIT2: This question could be solved by just reading the docs and / I posted too early without understanding the multithreaded/parallel nature of dots. So this thread remains for other ECS newbies who could potentially have the same problem and did not properly read the docs as I did :D

    When using EntityManager.AddComponent from a inside a system's OnUpdate method I observe that queries will not find the entities which received the component in the same OnUpdate call. I'm just starting with ECS and read that adding components will create sync points. My guess is it has something to do with these as the query sometimes succeeds in the next OnUpdate call when returning after using AddComponent(line 24).

    I need a way to guarantee the query will always find the entities with the newly added components.

    Could a solution be to use a command buffer for adding the component, then directly playing it back? Or is it not a good practice to use Components as Tags for filtering?

    EDIT: I tried the command buffer approach which seems to work, need further testing to fully confirm it!

    Here's the simplified code:

    In the original code the instructions inside of OnUpdate are not called every OnUpdate-call - I wrote it that way for better readability:

    Code (CSharp):
    1. protected override void OnCreate()
    2. {
    3.     EntityQuery _queryForTagA = GetEntityQuery(ComponentType.ReadOnly<TagA>());
    4.     EntityQuery _queryForTagB = GetEntityQuery(ComponentType.ReadOnly<TagB>());
    5. }
    6.  
    7. protected override void OnUpdate()
    8. {
    9.     NativeArray<Entity> entitiesA = _queryForTagA.ToEntityArray(Allocator.Temp);
    10.  
    11.     NativeList<Entity> entitiesToChange = new NativeList<Entity>(entitiesA.Length, Allocator.Temp);
    12.     for(int i = 0; i < entitiesA.Length; i++)
    13.     {
    14.         if(someCondition)
    15.         {
    16.             entitiesToChange.Add(entitiesA[i]);
    17.         }
    18.     }
    19.  
    20.     if(entitiesToChange.Length > 0)
    21.     {
    22.         EntityManager.RemoveComponent<TagA>(entitiesToChange);
    23.         EntityManager.AddComponent<TagB>(entitiesToChange);
    24.         //returning from here makes the query succeed
    25.     }
    26.  
    27.     [..]
    28.  
    29.     //the entities from the entitiesToChange-list are not included in the entitiesB-array
    30.     NativeArray<Entity> entitiesB = _queryForTagB.ToEntityArray(Allocator.Temp);
    31. }
     
    Last edited: Aug 6, 2022