Skip to content

Game.EndFrameBarrier

Assembly: Assembly-CSharp (game)
Namespace: Game

Type: public class

Base: SafeCommandBufferSystem

Summary:
EndFrameBarrier is a game/system-level barrier used at the end of a frame to coordinate Unity Job System producer jobs and to measure frame CPU elapsed time. It holds and completes a combined producer JobHandle each update, and it uses a Stopwatch to record the elapsed time between updates (exposed as lastElapsedTime and currentElapsedTime). The class is decorated with Preserve attributes on lifecycle methods so it is not stripped by code stripping; it is intended to be used by systems or mods that need to register or wait on producer jobs before finalizing end-of-frame command buffers.


Fields

  • private System.Diagnostics.Stopwatch m_Stopwatch
    This Stopwatch instance measures the elapsed CPU time between system updates. It is created in OnCreate, started/stopped around the OnUpdate flow, and stopped in OnDestroy. The elapsed times reported by currentElapsedTime and lastElapsedTime are computed from this Stopwatch (ElapsedTicks / Stopwatch.Frequency).

  • private Unity.Jobs.JobHandle <producerHandle>k__BackingField
    Backing field for the public producerHandle property. It holds the combined JobHandle of all producer jobs added via AddJobHandleForProducer. On each update the system calls Complete() on this handle to ensure producer jobs finish before the barrier proceeds, and then it resets the handle to default.

Properties

  • public Unity.Jobs.JobHandle producerHandle { get; private set }
    Exposes the combined producer JobHandle. The setter is private; code should call AddJobHandleForProducer(JobHandle) to add producer job dependencies. OnUpdate completes this handle (blocking until the jobs finish) and then resets it to default. Note: the class also exposes:
  • public float lastElapsedTime { get; private set; } — the measured elapsed time (in seconds) from the last frame/update, updated on OnUpdate.
  • public float currentElapsedTime => (float)m_Stopwatch.ElapsedTicks / (float)Stopwatch.Frequency — current running elapsed time since the stopwatch was last started, in seconds.

Constructors

  • public EndFrameBarrier()
    Default constructor. Does not initialize the Stopwatch directly — initialization happens in OnCreate. The constructor is preserved but otherwise empty.

Methods

  • protected virtual OnCreate() : System.Void
    Overrides the base system creation lifecycle. Calls base.OnCreate() and allocates/initializes m_Stopwatch. Marked with Preserve so it remains available after stripping.

Additional important methods (not listed in the header above) — described here for completeness: - protected override void OnDestroy()
Stops the stopwatch and calls base.OnDestroy(). Ensures the stopwatch is not left running when the system is destroyed. - protected override void OnUpdate()
Flow: 1. Stops the stopwatch. 2. Stores the elapsed time into lastElapsedTime (ElapsedTicks / Stopwatch.Frequency). 3. Resets the stopwatch. 4. Calls producerHandle.Complete() to wait for all registered producer jobs to finish. 5. Resets producerHandle to default(JobHandle). 6. Starts the stopwatch again. 7. Calls base.OnUpdate(). This method is annotated with MethodImplOptions.NoInlining and Preserve. Note: calling Complete() will block the main thread until the jobs finish — use judiciously to avoid stalls. - public new void AddJobHandleForProducer(JobHandle producerJob)
Combines the provided producerJob into producerHandle via JobHandle.CombineDependencies. Use this from producer systems to register their job handles so the barrier will wait for them at end-of-frame.

Usage Example

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

Additional usage notes: - Typical usage: producer systems call endFrameBarrier.AddJobHandleForProducer(theirJobHandle) so that the barrier completes them on OnUpdate. - The time values (lastElapsedTime and currentElapsedTime) are expressed in seconds and computed from Stopwatch ticks divided by Stopwatch.Frequency. - Be careful: producerHandle.Complete() is a blocking call — if long-running jobs are combined, it will stall the main thread until completion. Use asynchronous patterns where possible or ensure jobs are short.