I understand that each of the built-in EntityCommandBufferSystem classes run at specific times – namely, the start and the end of each major system group.
However, here’s what I don’t get: this DOTS Tutorial makes frequent use of
BeginSimulationEntityCommandBufferSystem. But, doesn’t that run before everything else in the SimulationGroup? I don’t understand how this would work correctly if the systems we’re creating are:
- implicitly going into the SimulationSystemGroup
- updating after BeginSimulationEntityCommandBufferSystem, since that thing has an attribute that says it should be the first thing that updates
Wouldn’t it make more sense to use EndSimulationEntityCommandBufferSystem? I know the tutorial says that some of its examples are suboptimal, but I don’t think it comments on the ECB ordering anywhere.
Assuming I’m correct here, it seems like writing into a begin-simulation ECB in the middle of the simulation group would…have no effect until the next frame, or something? I’d expect structural changes to completely invalidate these operations, so that doesn’t make sense…
A second, somewhat related issue:
I thought I needed to add my own EntityCommandBufferSystem – I wanted to run all of my entity-spawning logic in a group, then operate on the spawned entities afterward, to prevent a one-frame flicker before colors, sizes, etc. were assigned.
My current understanding is that if I want system B to operate on an entity produced by system A (or to notice added/removed components, or notice changed shared components, etc.), I must have a sync point between the two, so that the command buffer can get played back.
I did work out that I didn’t need to do this, though: I put the spawning system before SimulationSystemGroup and used BeginSimulationEntityCommandBufferSystem for ECBs, then put the post-spawning systems inside SimulationSystemGroup and used EndSimulationEntityCommandBufferSystem (the Begin one still flickered)
…so I guess that answers my first question . But, now I’m very curious about how those commands can survive for an entire frame and still be valid!
Anyway, suppose that I did need to create a new system. The docs say that subclassing EntityCommandBufferSystem with an empty class body is fine.
However, every example I’ve seen creates an ECB like this…
var ecbSingleton = SystemAPI.GetSingleton<EndSimulationEntityCommandBufferSystem.Singleton>();
var ecb = ecbSingleton.CreateCommandBuffer(state.WorldUnmanaged);
Note the Singleton field. It is not part of the abstract EntityCommandBufferSystem class, so I guess I need to define it myself – but I have no idea what the expected behavior is!
Inspecting BeginSimulationEntityCommandBufferSystem in VSCode shows this snippet (without a body)
public struct Singleton : IComponentData, IQueryTypeParameter, IECBSingleton
{
public EntityCommandBuffer CreateCommandBuffer(WorldUnmanaged world);
public void SetAllocator(Allocator allocatorIn);
public void SetPendingBufferList(ref UnsafeList<EntityCommandBuffer> buffers);
}
Is there some boilerplate I can paste in here? Alternatively, is there a “better” way to be accessing these systems that doesn’t involve the singleton?