Search Unity

Question FixedList<Entity> instead of DynamicBuffer = entities from another world?

Discussion in 'Entity Component System' started by Neonage, Feb 1, 2021.

  1. Neonage

    Neonage

    Joined:
    May 22, 2020
    Posts:
    287
    So I've tried to use FixedList64/128 instead of DynamicBuffer<Entity> so I can easily have a small set of entities wherever I need:
    Code (CSharp):
    1. public struct EntityList7 : IComponentData
    2. {
    3.     private FixedList64<Entity> entities;
    4.    
    5.     public Entity this[int index]
    6.     {
    7.         get => entities[index];
    8.         set => entities[index] = value;
    9.     }
    10.     // more wrapper stuff goes there...
    11. }
    I fill it with entities in my authoring component using GetPrimaryEntity(), just as usual:
    Code (CSharp):
    1. public override void OnConvert(Entity entity)
    2. {
    3.     var list = new EntityList7();
    4.     foreach (var receiver in targetReceivers)
    5.     {
    6.         list.Add(Conversion.GetPrimaryEntity(receiver));
    7.     }
    8.     AddComponentData(entity, list);
    9. }
    10.  
    And then, when I use this FixedList<Entity> inside ForEach - it returns entities of the same indicies, but from Conversion world. (eg. "(42:1) ShadowCube" instead of "(42:1) Turret")
    The following code produces an error:
    Code (CSharp):
    1. Entities.ForEach((in EntityList7 receivers) =>
    2. {
    3.     for (int i = 0; i < receivers.Length; i++)
    4.         SetComponent(receivers[i], new Target(hit.Entity));
    5. })
    Simply switching to DynamicBuffer<Entity> instead works! How this could be?

    My guess was that it has something to do with FixedList's bits and bytes shifting, but hey, the Entity itself doesn't contain any information about the world it lives in - only the EntityManager that you use matters, and it's from "Default World" in both cases. :confused:


    So right now I've ended up using Small Buffer by Jackson Dunstan. It works perfectly, and I guess is faster, because no byte or math operations are involved.
    I'll stick with this cool technique, but would like to know what causes such problems for FixedList<Entity>!
     
  2. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,759
    Because FixedList64 is just a fixed struct of bytes.

    upload_2021-2-2_9-7-35.png

    It's just remapped to <T> when you access to element

    Code (CSharp):
    1. public T this[int index]
    2. {
    3.     get
    4.     {
    5.         FixedList.CheckElementAccess(index, length);
    6.         unsafe
    7.         {
    8.             return UnsafeUtility.ReadArrayElement<T>(Buffer, CollectionHelper.AssumePositive(index));
    9.         }
    10.     }
    11.     set
    12.     {
    13.         unsafe
    14.         {
    15.             UnsafeUtility.WriteArrayElement<T>(Buffer, CollectionHelper.AssumePositive(index), value);
    16.         }
    17.     }
    18. }

    There's no way for the serializing systems to know you're using an Entity that needs remapping. You could have anything stored in there.

    The TypeManager on the other hand has knowledge of all IBufferElement types used in DynamicBuffer and also knows every one that has an Entity field and can use this to do remapping.

    -edit-

    If you look at the ComponentType struct you'll notice it has a property called HasEntityReferences
     
    Neonage and Nyanpas like this.