Search Unity

Question IBufferElementData / Dynamic Buffer Component confusion, how to stay under Capacity?

Discussion in 'Entity Component System' started by Botaurus, Jan 28, 2023.

  1. Botaurus

    Botaurus

    Joined:
    Feb 20, 2013
    Posts:
    81
    I'm making a DamageDealer component (such as a bullet). I need them to track what entities that have already collided with so that they don't deal damage to the same entity each frame. I'm looking into using a Dynamic Buffer Component. If I want to use this in an IJobEntity. I see I can pass in the dynamic buffer as a ReadOnly BufferLookup. But to record to the dynamic buffer, it looks like the EntityCommandBuffer only has an 'append' to buffer. So my question is, how do I stay under capacity if I can't write to a specific index or remove from the dynamic buffer; I can only append?
    Any suggestions welcome, thank you



    Code (CSharp):
    1.     public struct DamageEntityTracker : IBufferElementData
    2.     {
    3.         public Entity Entity;
    4.         public float Time;
    5.     }
     
  2. MaNaRz

    MaNaRz

    Joined:
    Aug 24, 2017
    Posts:
    117
    Writing to any Index in a DynamicBuffer would not be safe by default when executed in parallel. Appending however is because you can guarantee that there is no race condition. Thats why you can only append to it in an ECB.

    Why do you need an ECB in the first place?

    Your job could look something like this:

    Code (CSharp):
    1. [BurstCompile]
    2.     private struct ProcessCollisionsJob : ICollisionEventsJob
    3.     {
    4.         public BufferLookup<CollisionInfoBuffer> collisionInfoBufferFromEntity;
    5.         public void Execute(CollisionEvent collisionEvent)
    6.         {
    7.             Entity entityA = collisionEvent.EntityA;
    8.             Entity entityB = collisionEvent.EntityB;
    9.            
    10.             if (collisionInfoBufferFromEntity.HasBuffer(collisionEvent.EntityA))
    11.             {
    12.                 collisionInfoBufferFromEntity[collisionEvent.EntityA].Add(new CollisionInfoBuffer { Value = entityB });
    13.             }
    14.            
    15.             if (collisionInfoBufferFromEntity.HasBuffer(collisionEvent.EntityB))
    16.             {
    17.                 collisionInfoBufferFromEntity[collisionEvent.EntityB].Add(new CollisionInfoBuffer {Value = entityA});
    18.             }
    19.         }  
    20.     }
     
    vanyfilatov likes this.
  3. Botaurus

    Botaurus

    Joined:
    Feb 20, 2013
    Posts:
    81
    I'm doing my casting in parallel, not using collision events (so I only have to cast every x frames)
    Doesn't your solution still only append, which can exceed the capacity?
    My question can be stated more generally: how do you stay under capacity with dynamicbuffers while using iJobEntity?
    I guess I can just monitor the average entity count bullets record, set the capacity a bit above that, and accept some will exceed capacity

    Thank you
     
    Last edited: Jan 28, 2023
  4. MaNaRz

    MaNaRz

    Joined:
    Aug 24, 2017
    Posts:
    117
    Yes the code i posted above is only appending but not in an ECB. I don't think you need to think about Capacity too much. If we assume your bullet is hitting 1-2 targets in 90% of cases then id just go with Capacity of 2. The rare cases your bullet hits 10 targets won't be noticable at all performance wise. Its most likely better to have more bullet entities in a chunk than never exceeding buffer capacity.
     
    Botaurus likes this.
  5. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    4,264
    DynamicBuffers will automatically resize. Set the [InternalBufferCapacity] to the most common count if that count occurs more than 50% of the time. Otherwise, set it to 0 unless you have a low number number of instances.
     
    Botaurus likes this.