How to reference list of prefabs in ECS systems

Hey there. Could you kind people give me a hint on how to set up and reference a read only list of prefabs in unity entities or point me in the right direction?

I want to have a simple list of items(prefabs) my player can pick up(destroy entity prefab) or drop(instantiate entity prefab).

In the old OOP Unity world i’d do that with an Array of Scriptable Objects on a GameObject in the Scene for ease of authoring and use it like an item database.

I figured i’d add an Item component with an index value for that list to my character when picking up an item and remove the component and instantiate a prefab for the item in the world when i want to drop an item. Simple as that, but prefabs are managed data.

I have looked into using SO’s and Blob Assets in ECS for that but i cant reference managed data in ECS systems if i understand that correctly.

I think i am missing some core concepts here since this is such a common requirement for any type of game basicly.

Authoring has a list of GameObject prefabs. Baker calls GetEntity on each element and stores the resulting entity in a DynamicBuffer.

1 Like

Thank you very much for pointing me in the right direction! You made my Day.

Here is a basic example of how i did it:

using System.Collections.Generic;
using Unity.Entities;
using UnityEngine;

[InternalBufferCapacity(10)] // lets say i can have 10 items in my list for now
public struct ItemBufferElement: IBufferElementData
{
    public Entity ItemEntity;
}
public struct ItemDatabase : IComponentData { }

[DisallowMultipleComponent]
public class ItemDatabaseAuthoring : MonoBehaviour
{
    public List<GameObject> items;

    public class Baker : Baker<ItemDatabaseAuthoring>
    {
        public override void Bake(ItemDatabaseAuthoring authoring)
        {

            var entity = GetEntity(TransformUsageFlags.Dynamic);
            var buffer = AddBuffer<ItemBufferElement>(entity);
            for (int i = 0; i < authoring.items.Count; i++)
            {
                buffer.Add(new ItemBufferElement
                {
                    ItemEntity = GetEntity(authoring.items[i], TransformUsageFlags.Dynamic)
                });
            }
            AddComponent<ItemDatabase>(entity);
        }
    }
}

I put this authoring component on a GameObject in my Subscene.

And this is how i reference it in my systems to spawn a prefab from the list:

var itemDatabase = SystemAPI.GetSingletonEntity<ItemDatabase>();
var itemBuffer = SystemAPI.GetBuffer<ItemBufferElement>(itemDatabase);
var prefabEntity = itemBuffer.ElementAt(index).ItemEntity;

Thanks again and have a nice day.

2 Likes

This sounds like you misunderstand InternalBufferCapacity.

https://docs.unity3d.com/Packages/com.unity.entities@1.0/api/Unity.Entities.InternalBufferCapacityAttribute.html

my takeaway from a turbo makes games video was that the number there should be as close as possible but never greater than my maximum intended number of elements in the buffer. And if i ever put more elements in the buffer the data is moved to the heap which would slow down access to that memory. That video was about entities 0.5 though. I’ll read up about it to understand it properly. Thanks again for the clarification.

1 Like