Simplifying the Conversion of Multiple Prefabs to Entities in Unity ECS

I attempted to simplify the conversion of many kinds of prefabs to entities by using the following approach, where I include FixedList128Bytes<Entity> inside an IComponentData. However, this resulted in InvalidEntity values. I suspect that FixedList128Bytes<Entity> is not compatible with the Baking process in Unity.

Here’s the code I used:

public struct Prefabs : IComponentData
{
    public FixedList128Bytes<Entity> CH_01;
    public FixedList128Bytes<Entity> CH_02;
    .
    .
    .
}

class PrefabsAuthoring : MonoBehaviour
{
    [Header("Character_01")]
    public GameObject[] CH_01_GO;

    [Header("Character_02")]
    public GameObject[] CH_02_GO;

    .
    .
    .
}

class PrefabsBaker : Baker<PrefabsAuthoring>
{
    public override void Bake(PrefabsAuthoring authoring)
    {
        var entity = GetEntity(TransformUsageFlags.Dynamic);

        var prefabs = new PrefabsBakerBaker();
        AddPrefabsToList(authoring.CH_01_GO, ref prefabs.Ch_01);
        AddPrefabsToList(authoring.CH_02_GO, ref prefabs.CH_02);
        
        AddComponent(entity);
    }

    private void AddPrefabsToList(GameObject[] prefabsGO, ref FixedList128Bytes<Entity> entityList)
    {
        for (int i = 0; i < prefabsGO.Length; i++)
        {
            var item = prefabsGO[i] != null ? GetEntity(prefabsGO[i], TransformUsageFlags.Dynamic) : Entity.Null;
            entityList.Add(item);
        }
    }
}

The Issue:

It seems that FixedList128Bytes<Entity> inside an IComponentData doesn’t work well with Unity’s Baking process, as it leads to InvalidEntity entries.

Question:

What would be the best approach to simplify the conversion of many kinds of prefabs into entities while avoiding this issue? Any hints or alternatives would be greatly appreciated!

---- Postscript ----

Why do I want to use FixedList?
It is because I want to prepare a SpawnRequest:IComponentData to be paired with Prefabs:IComponentData and Instantiate with SpawnSystem, as shown below.

public struct SpawnRequest : IComponentData {
    public FixedList128Bytes<int> CH_01_SpawnNums;
    public FixedList128Bytes<int> CH_02_SpawnNums;
    .
    .
    .
}


public partial struct SpawnSystem : ISystem
{
    public void OnUpdate(ref SystemState state){
        ...
        for (int i = 0; i < prefabs.CH_01.Length; i++)
        {
            for (int i = 0; i < spawnRequest.CH_01_SpawnNums; i++)
            {
                ECB.Instantiate(prefabs.CH_01[i);
            }
        }
    }
}

A normal pattern is to create a dynamic buffer component type for the elements.

[InternalBufferCapacity(31)]
struct MyBufferElement : IBufferElementData
{
    public Entity Value;
}

If you know the upper bound of elements ahead of time, you can use InternalBufferCapacityAttribute to configure the amount of elements that get stored in the chunk per entity. Going over this limit for an entity will cause the buffer to be reallocated outside the chunk.

The deal with FixedList128Bytes etc. is that the logic that sets up Entity remapping is based on known fields. You could create a custom struct type with a number of Entity fields and provide an accessor to access the elements as an array if you need to.

struct EntityContainer4
{
    public const int Count = 4;
    Entity V0, V1, V2, V3;

    public unsafe ref Entity this[int index]
    {
        get
        {
            if ((uint)index >= Count)
            {
                throw new IndexOutOfRangeException();
            }
            fixed (Entity* v0 = &V0)
            {
                return ref v0[index];
            }
        }
    }
}

Thank you for your response! The second idea you presented was a method I didn’t know about. I find it a bit difficult, but I think it is a good idea.
*I have added to my first post why I want to use FixedList.

That’s probably something closer to this, then.

struct EntityContainer4
{
    public const int Capacity = 4;
    public int Count => _count;
    private int _count;
    Entity V0, V1, V2, V3;

    public void Add(Entity value)
    {
        if (_count >= Capacity)
        {
            throw new InvalidOperationException();
        }
        _count++;
        this[_count - 1] = value;
    }
    
    public void RemoveAt(int index)
    {
        if ((uint)index >= _count)
        {
            throw new IndexOutOfRangeException();
        }
        for (int i = index + 1; i < _count; i++)
        {
            this[i - 1] = this[i];
        }
        _count--;
    }

    public void RemoveAtSwapBack(int index)
    {
        if ((uint)index >= _count)
        {
            throw new IndexOutOfRangeException();
        }
        this[index] = this[_count - 1];
        _count--;
    }

    public unsafe ref Entity this[int index]
    {
        get
        {
            if ((uint)index >= _count)
            {
                throw new IndexOutOfRangeException();
            }
            fixed (Entity* v0 = &V0)
            {
                return ref v0[index];
            }
        }
    }
}