Array of prefabs in IComponentData

I would like to add an array of prefabs to an IComponentData to select between them in a system for which to instantiate. I have however been unable to find how I can get an array of Gameobjects/Entities.

Why do they need to be on a component? Why can’t you just store them in the system.

They do not need to be in a component. How can I have them in a system? Is it possible to connect prefabs to a system directly?

For prefabs map (we implemented our uniqueID system for keys) we have class IComponentData which is Singleton entity with NativeHashMap which in turn stores all entity prefabs converted from Addressables, and in the system, we just use GetSingleton for getting the map and accessing prefabs when required.

1 Like

Thanks, I will research on these keywords and try to create this infrastructure

Use a DynamicBuffer (IBufferElementData) instead of an IComponentData for this.

That I have tried, but to my understanding Gameobject does not work and having Entity still means that I cant add them via the editor.

[GenerateAuthoringComponent]
public struct EntityPrefabs : IBufferElementData
{
    public Entity prefabs;
}

Interested in this approach, could you explain what a “class IComponentData which is Singleton entity with NativeHashMap” looks like or maybe point me to an example ?

Are you not converting your GameObject prefabs to Entity prefabs?

/// <summary>
    /// Singleton component for storing all game prefabs
    /// </summary>
    public class PrefabsMapSingleton : IComponentData
    {
        /// <summary>
        /// Global prefabs map, use <see cref="ObjectBaseDefinition.objectId"/> as key
        /// </summary>
        public NativeHashMap<int, Entity> prefabsMap;
    }

Which is populated at app start after loading Addressables and converting them to prefabs at once.

1 Like

Yes I am, it however I dont think is possible right now to add the entities to the buffer using the editor and instead it can be done with a system. Is that what you meant?

Just implement IConvertGameObjectToEntity, IDeclareReferencedPrefab instead of GenerateAuthoringComponent and do what you want

I don’t think it has have ever occurred to me to implement IComponent in a class. So you are just able to request that Singleton in your SystemBase and pass the NativeHashMap to jobs. Are there any cases this doesn’t work well or have limitations. If you don’t mind I’m going to steal this and try it I’m my project.

You can actually query class based IComponentData in Entities.ForEach(), but obviously only with burst turned off.
It’s a very convenient way of linking legacy and ecs based code.

Not the best example but give you an idea. Is what eizenhorn was suggesting

[DisallowMultipleComponent]
[RequiresEntityConversion]
public class PlanetPrefabLibraryAuthoring : MonoBehaviour, IConvertGameObjectToEntity, IDeclareReferencedPrefabs
{
    public PlanetContainerPrefabLibraryData prefabLibrary;

    public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem)
    {
        // Create a spawner library on planet entity
        dstManager.AddBuffer<PlanetPrefabSpawnerLibraryBuffer>(entity);
        var buffer = dstManager.GetBuffer<PlanetPrefabSpawnerLibraryBuffer>(entity);
        for (var i = 0; i < prefabLibrary.tilePrefab.Length; i++)
        {
            var bufferElemData = new PlanetPrefabSpawnerLibraryBuffer
            {
                tilePrefabEntity = conversionSystem.GetPrimaryEntity(prefabLibrary.tilePrefab[i].gameObject)
            };

            buffer.Add(bufferElemData);
        }
    }

    public void DeclareReferencedPrefabs(List<GameObject> referencedPrefabs)
    {
        for (var i = 0; i < prefabLibrary.tilePrefab.Length; i++) referencedPrefabs.Add(prefabLibrary.tilePrefab[i].gameObject);
    }
}

Really !! i did not know. Is this a common pattern people are using or is it more our of necessity

It seems that I managed to fix it, thanks.

    public static Entity[] towerEntities;
    public GameObject[] towerPrefabs;

    public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem)
    {
        towerEntities = new Entity[towerPrefabs.Length];
        for (int i = 0; i < towerPrefabs.Length; i++)
        {
            Entity towerPrefabEntity = conversionSystem.GetPrimaryEntity(towerPrefabs[i]);
            TowerEntityTypePrefabs.towerEntities[i] = towerPrefabEntity;
        }
    }

    public void DeclareReferencedPrefabs(List<GameObject> referencedPrefabs)
    {
        for(int i = 0; i < towerPrefabs.Length; i++)
        {
            referencedPrefabs.Add(towerPrefabs[i]);
        }
    }