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. Dismiss Notice

EntityManager operations not allowed in ForEach when looping DynamicBuffer

Discussion in 'Entity Component System' started by jeremies_unity, Sep 18, 2019.

  1. jeremies_unity

    jeremies_unity

    Joined:
    Oct 16, 2018
    Posts:
    26
    The 0.1.0 patch notes mentioned:
    However, when EntityManager is used inside a DynamicBuffer `foreach`, I get the following error:
    This is the code to reproduce:
    Code (CSharp):
    1. using Unity.Entities;
    2.  
    3. public struct Tag : IComponentData
    4. {
    5. }
    6.  
    7. [InternalBufferCapacity(4)]
    8. public struct BufferData : IBufferElementData
    9. {
    10.     public float Value;
    11. }
    12.  
    13. public class TestSystem : ComponentSystem
    14. {
    15.     protected override void OnUpdate()
    16.     {
    17.         Entities.ForEach((Entity entity, DynamicBuffer<BufferData> buffer) =>
    18.         {
    19.             foreach (BufferData bufferData in buffer)
    20.             {
    21.                 if (!EntityManager.HasComponent<Tag>(entity))
    22.                 {
    23.                     EntityManager.AddComponentData(entity, new Tag());
    24.                 }
    25.             }
    26.         });
    27.     }
    28. }
    The DynamicBuffer is filled with 4 values at entity conversion time. Is this error by design or a bug?
     
  2. Singtaa

    Singtaa

    Joined:
    Dec 14, 2010
    Posts:
    485
    Tested your code and can confirm. After the
    EntityManager.AddComponentData
    ,
    buffer
    will be deallocated. Should be a bug.

    For the time being, you'll have to keep doing
    EntityManager.GetBuffer<BufferData>(entity)
    after every structural change.
     
  3. RoughSpaghetti3211

    RoughSpaghetti3211

    Joined:
    Aug 11, 2015
    Posts:
    1,695
    Can you update with bug report if you file one. I would love to track this
     
  4. jeremies_unity

    jeremies_unity

    Joined:
    Oct 16, 2018
    Posts:
    26
  5. JPrzemieniecki

    JPrzemieniecki

    Joined:
    Feb 7, 2013
    Posts:
    33
    Pretty sure this is by design.

    DynamicBuffer is a pointer to an array (usually stored inline in the chunk). When you add the Tag component you move the entity and its components (including the array) to another archetype/chunk, but the pointer still points to the old location, so it is correctly recognized as invalid.
    Could use a better error message I guess.
     
    tarahugger likes this.
  6. jeremies_unity

    jeremies_unity

    Joined:
    Oct 16, 2018
    Posts:
    26
    But isn't it the same with all EntityManager operations inside a ForEach? To me it's weird that the new version handles only some of the chunk-altering methods.
     
  7. JPrzemieniecki

    JPrzemieniecki

    Joined:
    Feb 7, 2013
    Posts:
    33
    The new (post-0.1.0) ForEach is more or less:

    Code (CSharp):
    1. var query = PrepareQuery();
    2. var entities = query.ToEntityArray();
    3. foreach (var entity in entities) {
    4.     var copy1 = GetComponent<SecondLambdaArg>(entity);
    5.     lambda(entity, ref copy1);
    6.     if (HasComponent<SecondLambdaArg>(entity)){
    7.         SetComponent(entity, copy1);
    8.     }
    9. }
    Entities are stable across structural changes and all their components are copied locally in the ForEach to make the ref stable.
     
    jeremies_unity likes this.
  8. Singtaa

    Singtaa

    Joined:
    Dec 14, 2010
    Posts:
    485
    Okay that makes sense. For perf reasons, probably not a good idea to also copy buffers around.
     
  9. farpini

    farpini

    Joined:
    Aug 9, 2018
    Posts:
    3
    I had the same issue and got that error today.

    JPrzemieniecki is right, it's an error by design.

    You can copy the buffer to a NativeArray using buffer.ToNativeArray and keep your code design using the EntityManager inside the loop without errors.
     
  10. jeremies_unity

    jeremies_unity

    Joined:
    Oct 16, 2018
    Posts:
    26
    Thanks everyone, this makes sense!