Almost there.
I’ve rewritten the lookup to the prefab to the NativeMultiHashMap<int, int> where key is prefab index in NativeArray prefab lookup. And values are it’s components pre-fetched in bootstrap phase converted to TypeIndex. (I hope they aren’t changed through runtime tho!)
Entity is found correctly and even spawned. One issue is that EntityCommandBuffer is not disposed correctly:
Here’s a current version
public class SpawnSystem : JobComponentSystem {
private EndFrameBarrier _endFrameBarrier;
[BurstCompile]
struct SpawnJob : IJobProcessComponentData<SpawnRequestData> {
[WriteOnly]
public EntityCommandBuffer.Concurrent Buffer;
[ReadOnly]
public NativeArray<Entity> Prefabs;
[ReadOnly]
public NativeMultiHashMap<int, int> PrefabComponents;
[NativeSetThreadIndex]
private int _threadIndex;
public void Execute(ref SpawnRequestData data) {
int tagIndex = data.EntityTagTypeIndex;
for (int i = 0; i < Prefabs.Length; i++) {
// Check if type of the component is the same as the type of the request component type
// Equals to if the entity has component of type
if (!PrefabComponents.TryGetFirstValue(i, out int firstIndex, out var iterator)) continue;
// Complete condition
if (CompareIndex(firstIndex, tagIndex, i)) return;
while (PrefabComponents.TryGetNextValue(out int typeIndex, ref iterator)) {
// Complete condition
if (CompareIndex(typeIndex, tagIndex, i)) return;
}
}
}
private bool CompareIndex(int typeIndex, int tagIndex, int prefabIndex) {
if (typeIndex != tagIndex) return false;
Buffer.Instantiate(_threadIndex, Prefabs[prefabIndex]);
return true;
}
}
protected override JobHandle OnUpdate(JobHandle inputDeps) {
SpawnJob spawnJob = new SpawnJob {
Prefabs = SpawnSystemExt.Prefabs,
PrefabComponents = SpawnSystemExt.PrefabComponents,
Buffer = _endFrameBarrier.CreateCommandBuffer()
.ToConcurrent()
};
JobHandle spawnHandle = spawnJob.Schedule(this, inputDeps);
return spawnHandle;
}
How do I “complete” the handle? Do I need to store the <jobHandle, spawnJob> and then iterate over their state in OnUpdate?
As I understood, I could use NativeQueue and iterate over it? In theory it should not make a difference. Although I was thinking about using an EntityEventSystem to push SpawnRequestData instead of spawning requests from inside systems.
It’s not implemented yet, as I’m trying to solve one problem at a time.
Usecase - Spawn a specific Entity Prefab based on the IComponentData tag / additional data (e.g. variation), without handling with an actual entity prefab (event/reactive manner) from inside of that System / Data.
A reason behind this: to avoid writing a ton of spawn systems for each projectile, player, enemy, or any other entity template / archetype that may be in-game and automatically fill them with proper data from the prefab data. (Possibly setting Position / Rotation if possible)