Search Unity

Question [SOLVED] Can't seem to Instantiate Prefabs from Lookup of any kind [ECS 1.0.0-pre.15]

Discussion in 'Entity Component System' started by Savage738, Jan 27, 2023.

  1. Savage738

    Savage738

    Joined:
    Jun 3, 2014
    Posts:
    3
    Hi as the title suggests, I currently want to load in prefabs in a baker, convert them to Entities and them store them in either a Native Array <Entity> or NativeHashMap<int, Entity> but none of these approaches seems to work, the idea is just a spawn system that can take the index of the prefab and then where it should spawn but it only spawns a cube or capsule when I have specific properties for them in my Components. I feel like I've tried everything at this point.

    They also seem to appear as these?

    upload_2023-1-27_7-30-3.png


    Baker:

    Code (CSharp):
    1. using Unity.Collections;
    2. using Unity.Entities;
    3. using Unity.Mathematics;
    4. using UnityEngine;
    5.  
    6. public class EntitySpawnManager : MonoBehaviour
    7. {
    8.     public GameObject PrefabToSpawn1;
    9.     public GameObject PrefabToSpawn2;
    10. }
    11.  
    12. public class EntitySpawnManagerBaker : Baker<EntitySpawnManager>
    13. {
    14.     public override void Bake(EntitySpawnManager authoring)
    15.     {
    16.         // todo: load data from json file database
    17.         //var test = Resources.Load("");
    18.  
    19.         // test
    20.         var prefab = GetEntity(authoring.PrefabToSpawn1);
    21.         var prefab2 = GetEntity(authoring.PrefabToSpawn2);
    22.  
    23.         //prefab.
    24.  
    25.         var prefabsMap = new NativeHashMap<int, Entity>(128, Allocator.Persistent)
    26.         {
    27.             { 0, prefab },
    28.             { 1, prefab2 }
    29.         };
    30.  
    31.         var toSpawn = new NativeList<SpawnComponent>(Allocator.Persistent);
    32.  
    33.         toSpawn.Add(new SpawnComponent()
    34.         {
    35.             EntityToSpawnIndex = 0,
    36.             Positions = new float3(1, 0, 1),
    37.             Rotations = quaternion.identity
    38.         });
    39.  
    40.         toSpawn.Add(new SpawnComponent()
    41.         {
    42.             EntityToSpawnIndex = 1,
    43.             Positions = new float3(1, 0, 1),
    44.             Rotations = quaternion.identity
    45.         });
    46.  
    47.         AddComponent(new EntitiesToSpawnContainer()
    48.         {
    49.             EntitiesToSpawn = toSpawn
    50.         });
    51.  
    52.         AddComponent(new EntityContainer()
    53.         {
    54.             PrefabsMap = prefabsMap
    55.         });
    56.     }
    57. }
    So called lookup:

    Code (CSharp):
    1. using System.Collections.Generic;
    2. using Unity.Collections;
    3. using Unity.Entities;
    4.  
    5. public struct EntityContainer : IComponentData
    6. {
    7.     public NativeHashMap<int, Entity> PrefabsMap;
    8. }

    Spawn System:

    Code (CSharp):
    1. using Assets.Scripts.ECS.Aspects;
    2. using System;
    3. using System.Diagnostics;
    4. using Unity.Burst;
    5. using Unity.Collections;
    6. using Unity.Entities;
    7. using Unity.Jobs;
    8. using Unity.Transforms;
    9.  
    10. namespace Assets.Scripts.Systems
    11. {
    12.     [BurstCompile]
    13.     //[UpdateAfter()]
    14.     public partial struct EntitySpawnSystem : ISystem
    15.     {
    16.         [BurstCompile]
    17.         public void OnCreate(ref SystemState state)
    18.         {
    19.             state.RequireForUpdate<EntityContainer>();
    20.         }
    21.  
    22.         [BurstCompile]
    23.         public void OnDestroy(ref SystemState state)
    24.         {
    25.  
    26.         }
    27.  
    28.         [BurstCompile]
    29.         public void OnUpdate(ref SystemState state)
    30.         {
    31.             var entityLookup = SystemAPI.GetSingletonEntity<EntityContainer>();
    32.             var aspect = SystemAPI.GetAspectRW<SpawnAspect>(entityLookup);
    33.  
    34.             if (!aspect.HasToSpawn) return;
    35.  
    36.             var ecb = SystemAPI.GetSingleton<BeginInitializationEntityCommandBufferSystem.Singleton>();
    37.  
    38.             var lookup = aspect.GetJobEntityLookup();
    39.             var componentSpawns = aspect.GetJobSpawnComponents();
    40.  
    41.             var buffer = ecb.CreateCommandBuffer(state.WorldUnmanaged).AsParallelWriter();
    42.  
    43.             var job = new EntitySpawnJob()
    44.             {
    45.                 ECB = buffer,
    46.                 EntitiesLookup = lookup,
    47.                 SpawnComponents = componentSpawns
    48.             }
    49.             .Schedule(aspect.NumberToSpawn, 16);
    50.  
    51.             job.Complete();
    52.  
    53.             //lookup.Dispose();
    54.             componentSpawns.Dispose();
    55.  
    56.             //ecb.
    57.  
    58.             //ecb.
    59.  
    60.             //ecb.Playback(state.EntityManager);
    61.         }
    62.     }
    63.  
    64.     public partial struct EntitySpawnJob : IJobParallelFor
    65.     {
    66.         [ReadOnly]
    67.         public NativeArray<SpawnComponent> SpawnComponents;
    68.  
    69.         [ReadOnly]
    70.         public NativeHashMap<int, Entity> EntitiesLookup;
    71.  
    72.  
    73.         public EntityCommandBuffer.ParallelWriter ECB;
    74.  
    75.         public void Execute(int index)
    76.         {
    77.             var toSpawn = SpawnComponents[index];
    78.             var bufferEntity = EntitiesLookup[toSpawn.EntityToSpawnIndex];
    79.  
    80.             //var entity = GetEntity()
    81.  
    82.             var entity = ECB.Instantiate(index, bufferEntity);
    83.  
    84.             ECB.AddComponent(index, entity, new LocalTransform
    85.             {
    86.                 Position = toSpawn.Positions,
    87.                 Rotation = toSpawn.Rotations,
    88.                 Scale = 1f
    89.             });
    90.         }
    91.     }
    92. }
    93.  

    Aspect:

    Code (CSharp):
    1. using Unity.Collections;
    2. using Unity.Entities;
    3.  
    4. namespace Assets.Scripts.ECS.Aspects
    5. {
    6.     public readonly partial struct SpawnAspect : IAspect
    7.     {
    8.         public readonly Entity Entity;
    9.  
    10.         public readonly RefRO<EntityContainer> EntitiesLookup;
    11.         public readonly RefRW<EntitiesToSpawnContainer> EntitiesToSpawn;
    12.  
    13.  
    14.         #region Properties
    15.  
    16.         public NativeHashMap<int, Entity> EntityMap
    17.         {
    18.             get => EntitiesLookup.ValueRO.PrefabsMap;
    19.         }
    20.  
    21.         public NativeList<SpawnComponent> SpawnComponents
    22.         {
    23.             get => EntitiesToSpawn.ValueRO.EntitiesToSpawn;
    24.         }
    25.  
    26.         #endregion
    27.  
    28.         public NativeHashMap<int, Entity> GetJobEntityLookup()
    29.         {
    30.             return EntityMap;
    31.         }
    32.  
    33.         public NativeArray<SpawnComponent> GetJobSpawnComponents()
    34.         {
    35.             var array = SpawnComponents.ToArray(Allocator.TempJob);
    36.  
    37.             return array;
    38.         }
    39.  
    40.         /// <summary>
    41.         /// There are currently values in entities to spawn
    42.         /// </summary>
    43.         public bool HasToSpawn => EntitiesToSpawn.ValueRO.EntitiesToSpawn.Length > 0;
    44.  
    45.         /// <summary>
    46.         /// The number of entities we should be spawning
    47.         /// </summary>
    48.         public int NumberToSpawn => EntitiesToSpawn.ValueRO.EntitiesToSpawn.Length;
    49.  
    50.         /// <summary>
    51.         /// Get an entity by it's lookup index
    52.         /// </summary>
    53.         /// <param name="index"></param>
    54.         /// <returns></returns>
    55.         public Entity GetEntityByIndex(int index)
    56.         {
    57.             var entity = EntitiesLookup.ValueRO.PrefabsMap[index];
    58.  
    59.             return entity;
    60.         }
    61.  
    62.         public SpawnComponent GetSpawnComponentByIndex(int index)
    63.         {
    64.             var spawnComponent = EntitiesToSpawn.ValueRO.EntitiesToSpawn[index];
    65.  
    66.             return spawnComponent;
    67.         }
    68.  
    69.         /// <summary>
    70.         /// Clear all entities to spawn, since we are done using it
    71.         /// </summary>
    72.         public void Clear()
    73.         {
    74.             //EntitiesToSpawn.ValueRW.EntitiesToSpawn.Clear();
    75.         }
    76.     }
    77. }
    78.  
     
  2. MaNaRz

    MaNaRz

    Joined:
    Aug 24, 2017
    Posts:
    117
    Have you tried storing the Prefabs in a DynamicBuffer instead of a NativeList? Might be an entities remapping issue with NativeContainers.

    The entities you do see are SystemEntities. Each System spawns one of those automatically in 1.0.
     
    bb8_1 and Savage738 like this.
  3. Savage738

    Savage738

    Joined:
    Jun 3, 2014
    Posts:
    3
    Hey, I will try and let you know thank you :)
     
  4. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,683
    You can't save native containers in components in baker as baking process serializes entities to disk and native containers not the part of that process, after deserializing you'll have default initialized container (not even allocated memory and IsCreated will return false) instead of what you expect, not to say you already have memory leak in baker (as you never dispose
    prefabsMap
    and
    toSpawn
    ). What you should use here is as mentioned above - DynamicBuffer or just plain Entity field on component.
     
    bb8_1, MaNaRz and Savage738 like this.
  5. Savage738

    Savage738

    Joined:
    Jun 3, 2014
    Posts:
    3
    Thank you for the amazing replies, the DynamicBuffer works :) was on this for days!

    @eizenhorn, I had a feeling the containers in the components was wonky I'll keep that in mind, thank you

    New Component Buffer:

    Code (CSharp):
    1. public struct EntityBufferLookup : IBufferElementData
    2. {
    3.     public Entity Entity;
    4. }
    5.  
    6.  

    Baker Changes:

    Code (CSharp):
    1. var buffer = AddBuffer<EntityBufferLookup>();
    2. buffer.Add(new EntityBufferLookup()
    3. {
    4.     Entity = prefab
    5. });
    6. buffer.Add(new EntityBufferLookup()
    7. {
    8.     Entity = prefab2
    9. });

    System Changes:

    Code (CSharp):
    1.         [BurstCompile]
    2.         public void OnUpdate(ref SystemState state)
    3.         {
    4.             var entityLookup = SystemAPI.GetSingletonEntity<EntityContainer>();
    5.             var aspect = SystemAPI.GetAspectRW<SpawnAspect>(entityLookup);
    6.             var buffer = SystemAPI.GetBuffer<EntityBufferLookup>(entityLookup);
    7.  
    8.             if (!aspect.HasToSpawn) return;
    9.  
    10.             var ecb = SystemAPI.GetSingleton<BeginInitializationEntityCommandBufferSystem.Singleton>();
    11.  
    12.             var lookup = aspect.GetJobEntityLookup();
    13.             var componentSpawns = aspect.GetJobSpawnComponents();
    14.  
    15.             var ecbParallel = ecb.CreateCommandBuffer(state.WorldUnmanaged).AsParallelWriter();
    16.  
    17.             var job = new EntitySpawnJob()
    18.             {
    19.                 BufferLookup = buffer,
    20.                 ECB = ecbParallel,
    21.                 EntitiesLookup = lookup,
    22.                 SpawnComponents = componentSpawns
    23.             }
    24.             .Schedule(aspect.NumberToSpawn, 16);
    25.  
    26.             job.Complete();
    27.  
    28.             //lookup.Dispose();
    29.             componentSpawns.Dispose();
    30.         }
    31.     }

    Job Changes:

    Code (CSharp):
    1. public partial struct EntitySpawnJob : IJobParallelFor
    2.     {
    3.         [ReadOnly]
    4.         public NativeArray<SpawnComponent> SpawnComponents;
    5.  
    6.         [ReadOnly]
    7.         public NativeHashMap<int, Entity> EntitiesLookup;
    8.  
    9.         [ReadOnly] public DynamicBuffer<EntityBufferLookup> BufferLookup;
    10.  
    11.         public EntityCommandBuffer.ParallelWriter ECB;
    12.  
    13.         public void Execute(int index)
    14.         {
    15.             var toSpawn = SpawnComponents[index];
    16.             var bufferEntity = BufferLookup[index];
    17.  
    18.             //var entity = GetEntity()
    19.  
    20.             var entity = ECB.Instantiate(index, bufferEntity.Entity);
    21.  
    22.             ECB.AddComponent(index, entity, new LocalTransform
    23.             {
    24.                 Position = toSpawn.Positions,
    25.                 Rotation = toSpawn.Rotations,
    26.                 Scale = 1f
    27.             });
    28.         }
    29.     }
    upload_2023-1-27_9-49-37.png
     
    bb8_1 and MaNaRz like this.