Factory Game: Creating Entity prefabs from ScriptableObject definitions

Currently I have an Item ScriptableObject that holds a gameobject Prefab.
I am using another scriptableobject class to define Recipes to combine Item inputs => Item outputs in X seconds of processing time

I have been banging my head against the wall trying to figure out how to spawn these items as entities and retain this data from the scritpable objects.

The prefabs in the Item.Prefab field do have an ItemAuthoring component that adds a ItemCompontn but so far I just have a single integer field for “lookupID” so I do realize these need to get baked at some point but I dont know how to do that programatically.

I was thinking ideally this lookup table lives in a NativeHashMap somewhere in a singleton entity where the Item GetHashCode() can serve as the key to the Entity prefab Value

Any tips appreciated.

[CreateAssetMenu(fileName = "Item", menuName = "Item", order = 1)]
public class Item : ScriptableObject
{
    public GameObject prefab;
    public int ItemID;

    private void OnValidate()
    {
        ItemID = HashCode.Combine(name, prefab);
    }
}

// for tracking items in world space
public struct ItemComponent : IComponentData
{
    public int ItemID;
    public Entity prefabEntity;
    public float PathPosition;
    public int QueueIndex;
}
---
public class ItemAuthoring : MonoBehaviour
{
    private class Baker : Baker<ItemAuthoring>
    {
        public override void Bake(ItemAuthoring authoring)
        {
            Entity entity = GetEntity(TransformUsageFlags.Dynamic);
            AddComponent(entity, new ItemComponent());
// FIXME?
        }
    }
}

so far this is what I tried and have no idea if this is heading in the right direction

public partial struct ItemService : ISystem
{
    private NativeHashMap<int, Entity> _itemMap;

    public void OnCreate(ref SystemState state)
    {
        _itemMap = new NativeHashMap<int, Entity>(100, Allocator.Persistent);
        LoadItemPrefabs(ref state);
    }
    private void LoadItemPrefabs(ref SystemState state)
    {
        // Load prefabs from Resources folder
        GameObject[] itemPrefabs = Resources.LoadAll<GameObject>("Items");

        foreach (GameObject prefab in itemPrefabs)
        {
            Entity entityPrefab =  //??? How to bake?
        }
    }

Baking is an editor-only operation. Built players must load data from serialized subscenes or manually build entities from the ground up.

One way to bake a bunch of global data is to have a dedicated subscene (or multiple) with a GameObject and authoring component with references to items you want to bake, each with a separate unique ID that you can use later on. For referencing a prefab, simply use IBaker.GetEntity(GameObject, TransformUsageFlags) to get a reference to the entity for that prefab GameObject. You could then add those references to a buffer component, or just rely on them being automatically included in the subscene with the GetEntity call and use queries in the build / Play Mode (with EntiyQueryOptions.IncludePrefab).

Include that subscene in your build by adding it to one of the scenes or with IEntitySceneBuildAdditions. Load that subscene at runtime. Usually, you’d just use queries to detect new entities from the newly loaded subscene that haven’t been accounted for in your lookup table, and set them up as necessary.

1 Like