Skip to content

Game.EndFrameBarrier

Assembly: Assembly-CSharp (Cities: Skylines 2 game assembly)
Namespace: Game

Type: class

Base: Unity.Entities.EntityCommandBufferSystem (game-specific end-of-frame barrier wrapping an ECB system)

Summary:
EndFrameBarrier is a barrier-style system used by the game's simulation to collect EntityCommandBuffer commands produced by jobs and to play them back at the end of a simulation frame (or frame-update tick). It is the central facility you should use when scheduling jobs that need to create, add or remove components or create/destroy entities from worker threads. Typical usage patterns in game code: create a command buffer (or ParallelWriter), schedule jobs that write to the buffer, then hand the job handle to the barrier so playback is correctly synchronized at the end of the frame. The system also exposes a producer job handle property so other systems can chain dependencies.


Fields

  • private System.Diagnostics.Stopwatch m_Stopwatch
    Used internally (typically for profiling or diagnostics) to measure how long barrier-related work (such as command buffer playback) takes. In the game's systems you will sometimes see the stopwatch started in OnCreate and used to track timings of barrier execution for debugging or telemetry.

  • private Unity.Jobs.JobHandle <producerHandle>k__BackingField
    Backing field for the public producerHandle property. Holds the JobHandle for the last scheduled producer job(s) that need to be completed before the barrier plays back. Other systems can inspect or use the producerHandle to chain job dependencies if necessary.

Properties

  • public Unity.Jobs.JobHandle producerHandle { get; private set }
    Exposes the producer JobHandle. After scheduling jobs that write to command buffers created by this barrier, you (or other systems) should call AddJobHandleForProducer(jobHandle) (or set this handle via system infrastructure) so the barrier knows which jobs must finish before playback. The property is read-only from outside; the barrier manages updating it.

Constructors

  • public EndFrameBarrier()
    Default constructor. The barrier is normally created/retrieved via World.GetOrCreateSystemManaged() inside system OnCreate methods. No special construction is required by typical mod code.

Methods

  • protected virtual OnCreate() : System.Void
    OnCreate initializes internal state of the barrier (for example, creating the stopwatch, registering with the world, and setting initial handles). When a user system obtains the EndFrameBarrier via World.GetOrCreateSystemManaged, you do not normally need to override EndFrameBarrier.OnCreate. Instead, in your systems call EndFrameBarrier.CreateCommandBuffer() and EndFrameBarrier.AddJobHandleForProducer(jobHandle) to integrate with it.

Additional common API surface (used in the game's codebase): - CreateCommandBuffer(): returns an EntityCommandBuffer which will be played back by the barrier at the end of the frame. - CreateCommandBuffer().AsParallelWriter(): returns a ParallelWriter for safe, parallel writes from jobs. When using the ParallelWriter you must supply the job's unfilteredChunkIndex (or use the job scheduling API that passes that index) when recording operations. - AddJobHandleForProducer(JobHandle): supply the JobHandle of jobs that produced commands so the barrier can ensure those jobs complete before playback.

Important behavioral notes: - Always call AddJobHandleForProducer for any job that writes to command buffers created by the barrier so playback won't race with unfinished jobs. - When using ParallelWriter, ensure each call that records commands uses the correct parallel index (typically the unfilteredChunkIndex provided by IJobChunk scheduling). - The barrier will play back its buffers at its scheduled time (here, end of frame/update). Failing to use the barrier properly can create race conditions or invalid entity operations.

Usage Example

[Preserve]
protected override void OnCreate()
{
    base.OnCreate();
    m_Stopwatch = new Stopwatch();
}

Additional minimal usage pattern (from systems like PropertyRenterSystem):

  • Acquire the barrier: var endFrameBarrier = World.GetOrCreateSystemManaged();

  • Create a parallel command buffer and schedule a job that writes to it: var ecbParallel = endFrameBarrier.CreateCommandBuffer().AsParallelWriter(); var jobHandle = someJob.ScheduleParallel(...);

  • Tell the barrier about the producer job handle so playback waits for the job: endFrameBarrier.AddJobHandleForProducer(jobHandle);

This ensures all entity mutations recorded in the job are applied once the barrier plays back at the end of the frame.