Create Entities In Other Worker Threads Failed

I try to create entities in other worker thread, not in main thread. I use ‘EntityCommandBuffer’ and encounter the error ’
NullReferenceException: Object reference not set to an instance of an object
Unity.Entities.BarrierSystem.CreateCommandBuffer () (at Library/PackageCache/com.unity.entities@0.0.12-preview.24/Unity.Entities/ComponentSystem.cs:713). ’
my codes here:
my barrier system

public class MyBarrier : BarrierSystem { }

job for creating entity

[BurstCompile]
struct SpawnECS : IJobParallelFor
{
    public EntityCommandBuffer commandBuffer;
    public EntityArchetype archetype;
    public NativeArray<Entity> entities;
    public void Execute(int index)
    {
        entities[index] = commandBuffer.CreateEntity(archetype);
    }
}

and in main thread

MyBarrier myBarrier = new MyBarrier();
public void Spawn()
{
    NativeArray<Entity> entities = new NativeArray<Entity>(100, Allocator.Temp);
    EntityCommandBuffer commandBuffer = myBarrier.CreateCommandBuffer();
    SpawnECS job = new SpawnECS
    {
        commandBuffer = commandBuffer,
        archetype = enemyParallelArchetype,
        entities = entities
    };
    JobHandle handle = job.Schedule(entities.Length, 1);
    handle.Complete();
    entities.Dispose();
}

Please help me to figure out the problem. Probably I use ‘EntityCommandBuffer’ in a wrong way, I will be appreciated to any example about creating entities by jobs.

More information:
Unity version 2018.3.7f1
Entities version 0.0.12-preview 24

Try the following:

MyBarrier myBarrier = World.Active.GetOrCreateSystem<MyBarrier>();

Anyway why are you scheduling a job for spawning entities?

Just use the batch API it’s much faster:

public void Spawn()
{
    using(var entities = new NativeArray<Entity>(100, Allocator.Temp)) {
         EntitiyManager.CreateEntity(enemyParallelArchetype, entities);
    }
}

Don’t use jobs for that!

Thank you for your answer.
Since all these entities are created in main thread, there will be frame drop, and I think if I create entites parallelly will avoid the issue. Am I on the right track?

I had to initialize NativeArray by Allocator.TempJob, and it works, but burst compiler raises an exception.
Unexpected exception Burst.Compiler.IL.CompilerException: Unexpected exception —> Burst.Compiler.IL.CompilerException: Error while processing function Unity.Entities.World Unity.Entities.World::get_Active() —> Burst.Compiler.IL.CompilerException: Unexpected error while processing IL_0000: ldsfld Unity.Entities.World Unity.Entities.World::<Active>k__BackingField at
C:\Projects\ecs_test\Library\PackageCache\com.unity.entities@0.0.12-preview.24\Unity.Entities\Injection\World.cs(42,38) —> System.NotSupportedException: The managed class type Unity.Entities.World is not supported. Loading from a static field Unity.Entities.World Unity.Entities.World::<Active>k__BackingField is not supported by burst
at Burst.Compiler.IL.ILVisitor.NotSupported (Burst.Compiler.IL.Syntax.ILInstruction inst)

maybe the same issue in this thread https://discussions.unity.com/t/710439

No. Entities will ALWAYS be created on the main thread.
Unless you’re doing a lot of setup/init in your thread, there should be no difference (using a cmdbuffer will have a bit more overhead).
CommandBuffers just schedule the work to be ran at a later time. The work itself (spawning, add/remove component, etc.) is still done on the main thread.

Doe the GetSystem() in your system, not your job (you’ll probably want to put it in OnCreateManager())
Then, create the commandbuffer (make it concurrent if you need to), and pass that to your job.
Don’t forget to add the JobHandle for your job to the producer of the commandbuffer using bufferSystem.AddJobHandleForProducer (this takes the handle that’s returned when scheduling your job)), and, if you can, use Unity’s built-in CommandBufferSystems to prevent having to run a seperate buffersystem.

ECB creates entities on main thread too, but later.

Not always.
ExclusiveEntityTransaction in different world gives you opportunity to create entities in other world on one of worker threads, without main thread block. Moving this entities to main thread world by MoveEntitiesFrom block main thread (but it’s other strory) but creation process itself on other thread in this EET case.

Glad to know these, thank you, eizenhorn and FrankvHoof.