Search Unity

How is SetBuffer different from AddBuffer for EntityCommandBuffer?

Discussion in 'Entity Component System' started by DK_A5B, Apr 5, 2019.

  1. DK_A5B

    DK_A5B

    Joined:
    Jan 21, 2016
    Posts:
    110
    Both methods have the same signatures (either parameterless or taking an Entity as the single parameter, and returning a DynamicBuffer for the specified type). The documentation for DynamicBuffers only talks about the AddBuffer method - which is used to add a DynamicBuffer. There's no mention of the SetBuffer method. I would expect it to be used to set the value of a DynamicBuffer, but there aren't any signatures that take additional parameters that would handle this.
     
  2. Spy-Shifty

    Spy-Shifty

    Joined:
    May 5, 2011
    Posts:
    546
    Use GetBufferFromEntity() from your system.

    You don't need to set Buffer because it's a pointer...
     
  3. DK_A5B

    DK_A5B

    Joined:
    Jan 21, 2016
    Posts:
    110
    Thanks Spy-Shifty, but I'm still unclear on what the purpose of SetBuffer() is and how it differs from AddBuffer(). To phrase it another way, I guess my question is "what does SetBuffer() do"?

    My understanding is:
    AddBuffer() - available from both EntityManager and EntityCommandBuffer - this is used to add a DynamicBuffer to an Entity. It returns the buffer, which you can then use to add elements to the buffer.
    GetBufferFromEntity() - available from JobComponentSystem - this is used to get a DynamicBuffer on an Entity.
    GetBuffer() - available from EntityManager - this is used to get a DynamicBuffer on on an Entity.

    But I can't see what SetBuffer() does. Right now I don't need it, I can achieve what I want with the other methods I understand, but I'd like to understand this other piece of the API in case it does something I might find useful later.
     
  4. Deleted User

    Deleted User

    Guest

    Probably if you want to modify entire DynamicBuffer. Lets say you built one temporary buffer in a job and you want completely overwrite the existing one.
     
  5. DK_A5B

    DK_A5B

    Joined:
    Jan 21, 2016
    Posts:
    110
    That's what I would assume, but the signature is the same as the AddBuffer() method. It doesn't take any parameters other than the Entity. So it isn't clear to me how it would be used to modify the entire buffer, since there's no way to pass in data to overwrite the existing buffer. Clearly there's something I'm missing.
     
  6. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,685
    Difference is AddBuffer adds new type to entity archetype and sets new, fresh buffer, and SetBuffer only sets new, fresh buffer for entity which already have this type in archetype.
    Code (CSharp):
    1.  
    2.                         case ECBCommand.AddBuffer:
    3.                             {
    4.                                 var cmd = (EntityBufferCommand*)header;
    5.                                 var entity = SelectEntity(cmd->Header.Entity, playbackState);
    6.                                 mgr.AddComponent(entity, ComponentType.FromTypeIndex(cmd->ComponentTypeIndex));
    7.                                 mgr.SetBufferRaw(entity, cmd->ComponentTypeIndex, &cmd->TempBuffer, cmd->ComponentSize);
    8.                             }
    9.                             break;
    10.  
    11.                         case ECBCommand.AddBufferWithEntityFixUp:
    12.                             {
    13.                                 var cmd = (EntityBufferCommand*) header;
    14.                                 var entity = SelectEntity(cmd->Header.Entity, playbackState);
    15.                                 mgr.AddComponent(entity, ComponentType.FromTypeIndex(cmd->ComponentTypeIndex));
    16.                                 SetBufferWithFixup(mgr, cmd, entity, playbackState);
    17.                             }
    18.                             break;
    19.  
    20.                         case ECBCommand.SetBuffer:
    21.                             {
    22.                                 var cmd = (EntityBufferCommand*)header;
    23.                                 var entity = SelectEntity(cmd->Header.Entity, playbackState);
    24.                                 mgr.SetBufferRaw(entity, cmd->ComponentTypeIndex, &cmd->TempBuffer, cmd->ComponentSize);
    25.                             }
    26.                             break;
    27.  
    28.                         case ECBCommand.SetBufferWithEntityFixUp:
    29.                             {
    30.                                 var cmd = (EntityBufferCommand*)header;
    31.                                 var entity = SelectEntity(cmd->Header.Entity, playbackState);
    32.                                 SetBufferWithFixup(mgr, cmd, entity, playbackState);
    33.                             }
    34.                             break;
    For example:
    Code (CSharp):
    1. Entity entityWithType    = EntityManager.CreateEntity(typeof(MyBuffer));
    2.             Entity entityWithoutType = EntityManager.CreateEntity();
    3.        
    4.             var ecb = new EntityCommandBuffer(Allocator.TempJob);
    5.             Debug.Log("On playback works fine, without error");
    6.             ecb.SetBuffer<MyBuffer>(entityWithType);
    7.             ecb.Playback(EntityManager);
    8.            
    9.             Debug.Log("On playback throw error, because entity hasn't MyBuffer in archetype");
    10.             ecb.SetBuffer<MyBuffer>(entityWithoutType);
    11.             ecb.Playback(EntityManager);
    12.             ecb.Dispose();
    upload_2019-4-6_11-22-36.png
     
    Last edited: Apr 6, 2019
    Tony_Max likes this.
  7. DK_A5B

    DK_A5B

    Joined:
    Jan 21, 2016
    Posts:
    110
    Thanks eizenhorn, that makes complete sense. So I'd use SetBuffer() in a situation where I have an entity belonging to an Archetype that already has the DynamicBuffer present, and where I want to initialize/re-initialize the buffer to a new, clean buffer. Whereas AddBuffer() is used on entities belonging to an Archetype that don't have the DynamicBuffer present already. AddBuffer() both adds the DynamicBuffer component to the entity (and therefore changes the Archetype of the entity as you point out) and initializes that buffer to a new buffer.

    I guess what was throwing me is I would expect a SetXXX() method to take a parameter to set the underlying property to something. Whereas the actual behavior of SetBuffer() is more like an InitBuffer() or ClearBuffer() method, in that it just "sets"/"resets" the existing buffer to a new instance of that buffer, rather than setting it to a specific value.

    Thanks for clearing that up!
     
  8. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,778
    Set buffer is like Set component equivalent.
    Similarly Add buffer, is equivalent to Add component.
    But appears, you get your answer already.