Use an entity command buffer
You can record entity command buffers (ECBs) in jobs, and on the main thread.
Use an entity command buffer in a job
You can't perform structural changes in a job, except inside an ExclusiveEntityTransaction, so you can use an ECB to record structural changes to play back after the job is complete. For example:
// Single-threaded scheduling using IJobEntity (replaces deprecated Entities.ForEach).
[BurstCompile]
partial struct AddBarJob : IJobEntity
{
public EntityCommandBuffer Ecb;
void Execute(Entity e, in FooComp foo)
{
if (foo.Value > 0)
{
// Record a command that will later add BarComp to the entity.
Ecb.AddComponent<BarComp>(e);
}
}
}
protected override void OnUpdate()
{
// Buffer grows as needed.
var ecb = new EntityCommandBuffer(Allocator.TempJob);
// Schedule a single job (not parallel) that records commands.
new AddBarJob { Ecb = ecb }.Schedule();
// Complete the job so we can play back on the main thread.
Dependency.Complete();
// Apply the recorded structural changes.
ecb.Playback(EntityManager);
// Dispose the ECB.
ecb.Dispose();
}
Parallel jobs
If you want to use an ECB in a parallel job, use EntityCommandBuffer.ParallelWriter, which concurrently records in a thread-safe way to a command buffer:
EntityCommandBuffer ecb = new EntityCommandBuffer(Allocator.TempJob);
// Methods of this writer record commands to
// the EntityCommandBuffer in a thread-safe way.
EntityCommandBuffer.ParallelWriter parallelEcb = ecb.AsParallelWriter();
Note
Only recording needs to be thread-safe for concurrency in parallel jobs. Playback is always single-threaded on the main thread.
For information on deterministic playback in parallel jobs, refer to the documentation on Entity command buffer playback
Use an entity command buffer on the main thread
You can record ECB changes on the main thread, such as in the following situations:
- To delay your changes.
- To play back a set of changes multiple times. To do this, refer to the information on multi-playback.
- To play back a lot of different kinds of changes in one consolidated place. This is more efficient than interspersing the changes across different parts of the frame.
Every structural change operation triggers a sync point, which means that the operation must wait for some or all scheduled jobs to complete. If you combine the structural changes into an ECB, the frame has fewer sync points.
Note
If you have a lot of the same types of commands in an ECB, and you can afford to make the change instantly, it can be faster to use the EntityManager variants on whole batches of entities at once.