Search Unity

How do I keep a float3[,] or float3[][] or any other arrays in an IComponentData?

Discussion in 'Entity Component System' started by Rs, Sep 7, 2019.

  1. Rs

    Rs

    Joined:
    Aug 14, 2012
    Posts:
    74
    I know I can't do that because it's not a bittable type. So how do I go about it?

    Is it better to keep it in a System? But if it's aJobComponentSystem, how do I pass it to the job?
     
  2. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,685
    IBufferElement
     
    Rs likes this.
  3. desertGhost_

    desertGhost_

    Joined:
    Apr 12, 2018
    Posts:
    260
    A dynamic buffer (implementing IBufferElementData) is what you should use. For a float[][] you can use the dynamic buffer (which is 1 dimensional) and convert your x,y indices into a single index using

    array[width * row + col] = value;
    .
     
  4. ndesy

    ndesy

    Joined:
    Jul 22, 2019
    Posts:
    20
    If you have small amount of items, you can use a ResizableArray64Byte in your IComponentData.
     
    Seb-1814, Rs, Singtaa and 1 other person like this.
  5. Rs

    Rs

    Joined:
    Aug 14, 2012
    Posts:
    74
    I tried with float3[][], float[][][] and also float[] with the serialization method you mention but all of them give the same error saying it's neither a primitive nor a bittable type.
     
  6. Rs

    Rs

    Joined:
    Aug 14, 2012
    Posts:
    74
    I'm not sure this is the right solution for me as I have a matrix of values which is technically a float3[][].
    I tried to switch to ResizableArray64Byte<ResizableArray64Byte<float3>> but I had a runtime error saying that Capacity was 0 when I was sure I had it all initialized (with
    new ResizableArray64Byte<ResizableArray64Byte<float3>>()
    ) and allocated using
    new ResizableArray64Byte<float3>();
    plus a number of
    ResizableArray64Byte.Add(...)


    I never used ResizableArray64Byte. Perhaps I have too many elements for ResizableArray64Byte?
     
  7. florianhanke

    florianhanke

    Joined:
    Jun 8, 2018
    Posts:
    426
    You need to use a dynamic buffer (https://docs.unity3d.com/Packages/com.unity.entities@0.1/manual/dynamic_buffers.html) instead of an e.g. float[], with IBufferElement elements (the example on https://docs.unity3d.com/Packages/com.unity.entities@0.1/manual/dynamic_buffers.html uses an IBufferElement with an int) in place of the floats.
     
    Rs likes this.
  8. ndesy

    ndesy

    Joined:
    Jul 22, 2019
    Posts:
    20
    ResizableArray64Byte is a fixed 64 bytes buffer, so you can't definitely nest them. it should be treated as a 1-dimensional array where the total size is less or equals to 64 bytes.

    I agree that it's not the right solution if you have a huge matrix. DynamicBuffer are probably your best bet.
     
  9. desertGhost_

    desertGhost_

    Joined:
    Apr 12, 2018
    Posts:
    260
    Here are some code fragments of using a dynamic buffer.

    Code (CSharp):
    1. //define data type
    2. public struct MyData : IDynamicBufferElement
    3. {
    4.     public float value;
    5. }
    6.  
    7. //add data
    8. entityManager.AddBuffer<MyData>(entity);
    9.  
    10. //access from main thread
    11. var buffer = EntityManager.GetBuffer<MyData>(entity);
    12.  
    13. //access from job where lookup is BufferFromEntity<MyData>
    14. var buffer = lookup[entity];
    15.  
    16. //adding an element
    17. buffer.Add(new MyData { value = afloatvalue });
    18.  
    19. //accessing 1d array
    20. var value = buffer[index].value;
    21.  
    22. //accessing 2d array
    23. var value = buffer[width * row + col];
     
  10. Rs

    Rs

    Joined:
    Aug 14, 2012
    Posts:
    74
    Thanks Florian. I'm sure I'll sound confused now. Is this really what fits considering the size would not change in dimension?
    Is it the best way to go to have a collection of float3? Do I have to implement a separate system to get/set these values or can I read from an existing one??

    Maybe my problems are more specific to my situation than I thought. Again, the goal here is to have a matrix of float3. I don't get how I make this visible to any Systems I create.
    If I have a System that acts on some (many) moving entities and these entities have to get a value from a force field (a float3[][] type) it sounds like it should be trivial to me.
     
    Last edited: Sep 10, 2019
  11. desertGhost_

    desertGhost_

    Joined:
    Apr 12, 2018
    Posts:
    260
    Here are two ways you could approach this problem:

    1. You could have your system that moves your entities with respect to the force field store the force in a native container similar to a float[][] (you could write a custom container or use a 1 dimensional native array with an index mapping scheme) allocated by that system.

    2. Have each cell of the force field be an entity that has component data:
    struct ForceFieldPoint : IComponentData{ float value; }
    . You would position these entities in a grid to form your force field. They would then be accessed with a query looking for entities with a ForceFieldPoint component.
     
    Rs likes this.