Proper way to directly reference an entity?

I have a front end SO template system for designers to create items:

public class ItemData
{
    public ushort id;
    public new string name;
    public string description;

Then I convert those items at runtime to entities (not as a baker) as item templates to use later (These entities would act as the blueprints for creating new items):

public partial class ConvertObjectToEntity : SystemBase
{

public struct ItemEntity: IComponentData
{
    public ushort id;
    public FixedString64Bytes name;
    public FixedString128Bytes description;
    public NativeArray<ChildrenEntity> children;

...

 void ConvertDataToEntity(Entity entity, ItemData itemData)
    {
        var newEntity = new ItemEntity
        {
            id = itemData.id,
            name = new FixedString32Bytes(itemData.name),
            description = new FixedString32Bytes(itemData.description),
            children = ConvertChildrenArrayToNativeArray(itemData.children, Allocator.Temp),

...
       entityManager.SetComponentData(entity, newEntity);

What would be the proper way to access the data once it exists as an entity for the creation of new items? (When I say access data, I mean the best way to reference a specific item in the entities) meaning if I wanted to create a specific Item, let’s say a Foo, what would be the recommended way of getting the Foo data, then creating a new entity of that kind that I would use in at runtime?

If you prefer that process of referencing this specific item Entity to be as simple as:

Entity foo = items["foo"];

then you would need to maintain a NativeHashMap<FixedString32Bytes,Entity> items; in a dedicated system or on a singleton Entity.

Luckily I have a repo that could serve as an example for you how to do that. It can be found here:

This utility project was designed to aid with turning GameObject prefabs into Entity prefabs and offering an easy way of finding them after game starts. It solves very similar problem once you let yourself think about these blueprint entities as a kind of prefabs you instantiate and customize.

This is how/where the NativeHashMap is stored:

There is a system that creates this as singleton and other systems that maintain it.

Item blueprints as baked prefabs

Here is a Prefab System implementation example where I bake ItemData via SubScene so it loads in game fast and let’s Prefab System convert them into prefab entities tracked in a hashmap mentioned earlier.

using UnityEngine;
using Unity.Entities;
using Unity.Collections;

#if UNITY_EDITOR
[DisallowMultipleComponent]
[AddComponentMenu( "Game/Item Prefab Authoring" )]
public class ItemPrefabAuthoring : MonoBehaviour
{

    // replace this array with a reference to that front-end SO that hosts the item data
    [SerializeField] ItemData[] _items = new ItemData[0];

    public class Baker : Baker<ItemPrefabAuthoring>
    {
        public override void Bake ( ItemPrefabAuthoring authoring )
        {
            if( authoring._items==null || authoring._items.Length==0 )
                return;

            Entity entity = this.GetEntity( authoring , TransformUsageFlags.None );

            var pool = AddBuffer<PrefabSystem.RequestPrefabPoolRegistration>( entity );
            foreach( var item in authoring._items )
            {
                Entity itemEntity = CreateAdditionalEntity( TransformUsageFlags.None );
                AddComponent<Prefab>( itemEntity );// this tag is removed from entities on Instantiate

                AddComponent( itemEntity , new ItemID{
                    Value = item.id ,
                } );
                AddComponent( itemEntity , new ItemName{
                    Value = item.name ,
                } );
                AddComponent( itemEntity , new ItemDescription{
                    Value = item.description ,
                } );
                var children = AddBuffer<ItemChild>( itemEntity );
                for( int i=0 ; i<3 ; i++ )
                {
                    children.Add( new ItemChild{
                        Value = (byte)i
                    } );
                }

                pool.Add( new PrefabSystem.RequestPrefabPoolRegistration{
                    PrefabID = item.name ,//item.id.ToString() ,
                    Prefab = itemEntity ,
                } );
            }
        }
    }

}
#endif

public struct ItemID : IComponentData
{
    public ushort Value;
}
public struct ItemName : IComponentData
{
    public FixedString64Bytes Value;
}
public struct ItemDescription : IComponentData
{
    public FixedString64Bytes Value;
}
public struct ItemChild : IBufferElementData
{
    public byte Value;// replace 'byte' by appropriate value type
}

[System.Serializable]
public class ItemData
{
    public ushort id;
    public string name;
    public string description;
}

using UnityEngine;
using Unity.Entities;

[RequireMatchingQueriesForUpdate]
public partial struct ItemPrefabInstantiationSystem : ISystem
{

	[Unity.Burst.BurstCompile]
	public void OnCreate ( ref SystemState state )
	{
		state.RequireForUpdate<PrefabSystem.Prefabs>();
	}

	[Unity.Burst.BurstCompile]
	public void OnDestroy ( ref SystemState state ) {}

	[Unity.Burst.BurstCompile]
	public void OnUpdate ( ref SystemState state )
	{
		var singleton = SystemAPI.GetSingleton<PrefabSystem.Prefabs>();
		var prefabs = singleton.Registry;
		var prefabsDependency = singleton.Dependency;

		if( Input.GetKeyDown(KeyCode.Space) )
		{
			prefabsDependency.Complete();
			Entity prefab = prefabs["lorem ipsum"];
			Entity instance = state.EntityManager.Instantiate( prefab );
		}
	}

}

This is how ItemPrefabAuthoring can bake all the ItemData into entities:

Item prefab after scene starts (note: Prefab tag present)

Item entity after instantiation by ItemPrefabInstantiationSystem (note: no Prefab tag)