Skip to content

Game.TrafficFlowSystem

Assembly:
Game

Namespace:
Game.Simulation

Type:
class

Base:
GameSystemBase

Summary:
TrafficFlowSystem is an ECS system responsible for updating traffic flow metrics for lanes and roads. It runs periodic updates (configured via UPDATES_PER_DAY and GetUpdateInterval) and schedules two Burst-compiled chunk jobs: - UpdateLaneFlowJob: interpolates lane flow data (duration/distance) over time. - UpdateRoadFlowJob: aggregates lane flows per road, updates CarLane flow offsets, and enqueues flow actions for the pathfinding queue.

The system uses TimeSystem to compute time-of-day weighting (m_TimeFactors), reads/writes LaneFlow and Road components, inspects SubLane buffers, and writes FlowActionData into a FlowAction queue consumed by the PathfindQueueSystem. It is designed to run over filtered entities using UpdateFrame shared components and leverages Unity's Jobs/ECS patterns for parallel, burst-compiled execution.

Fields

  • public const int UPDATES_PER_DAY = 32
    This constant controls how many discrete flow update frames there are per day/time-cycle. It is used by the system when computing update frames and scheduling.

  • private SimulationSystem m_SimulationSystem
    Reference to the SimulationSystem in the world. Used to read the current simulation frame index for scheduling the per-frame updates.

  • private PathfindQueueSystem m_PathfindQueueSystem
    Reference to the PathfindQueueSystem. The system enqueues FlowAction objects to this system after computing flow changes (so pathfinding/vehicle behavior can react).

  • private TimeSystem m_TimeSystem
    Reference to TimeSystem. Used to compute normalized time-of-day which influences flow weighting (time factors).

  • private EntityQuery m_LaneQuery
    Query used to select entities that have LaneFlow and need updating (includes UpdateFrame shared component, excludes Deleted/Temp). Used to schedule UpdateLaneFlowJob.

  • private EntityQuery m_RoadQuery
    Query used to select Road entities (having SubLane buffer and UpdateFrame) for aggregation and CarLane updates. Used to schedule UpdateRoadFlowJob.

  • private TypeHandle __TypeHandle
    Container for ECS type handles and lookups used by this system's jobs. It stores EntityTypeHandle, ComponentTypeHandles, BufferTypeHandles and ComponentLookup instances and is assigned in OnCreateForCompiler.

Properties

  • None (no public properties exposed by this system)

Constructors

  • public TrafficFlowSystem()
    Default public constructor. The system is a managed GameSystemBase and is created by the World/Systems bootstrap. No custom initialization is performed here; setup happens in OnCreate.

Methods

  • public override int GetUpdateInterval(SystemUpdatePhase phase)
    Returns the update interval for this system. In this implementation it returns 512 (frames), which controls when the system is invoked relative to other systems.

  • protected override void OnCreate()
    Initializes the system:

  • Acquires references to SimulationSystem, PathfindQueueSystem, and TimeSystem from the World.
  • Builds entity queries for lanes and roads (including UpdateFrame filters and excluding Deleted/Temp).
  • Calls RequireAnyForUpdate with the lane and road queries so the system runs only when relevant entities exist.

  • protected override void OnUpdate()
    Main update logic executed when the system runs:

  • Computes time-of-day factors (float4 x) based on TimeSystem.normalizedTime; used to weight interpolation/flow calculations across the day.
  • Builds a FlowAction queue (FlowAction with Allocator.Persistent) to collect per-lane flow offset change actions.
  • Sets shared-component filters on m_LaneQuery and m_RoadQuery using SimulationUtils.GetUpdateFrame to select the subset of entities to update this tick.
  • Schedules UpdateLaneFlowJob (interpolates LaneFlow.m_Duration/m_Distance towards m_Next using m_TimeFactors).
  • Schedules UpdateRoadFlowJob which:
    • Iterates Road entities' SubLane buffers, aggregates lane flow durations/distances into Road traffic flow accumulators (m_TrafficFlowDuration0/1, m_TrafficFlowDistance0/1).
    • Uses NetUtils.GetTrafficFlowSpeed to compute per-master-lane flow speed, updates CarLane.m_FlowOffset when the weighted dot product with time factors changes, and enqueues a FlowActionData for each changed lane.
  • Enqueues the FlowAction to the PathfindQueueSystem and sets the system's job dependency.

  • private void __AssignQueries(ref SystemState state)
    Internal helper stub used by compiler-generated code. In this implementation it creates and immediately disposes an EntityQueryBuilder; the real handle assignments take place in __AssignHandles via __TypeHandle.

  • protected override void OnCreateForCompiler()
    Compiler helper that calls __AssignQueries and assigns type handles by calling __TypeHandle.__AssignHandles with the system state. This ensures the TypeHandle contains up-to-date ECS handles required by jobs.

  • Nested job: UpdateLaneFlowJob.Execute(in ArchetypeChunk chunk, ...)
    Burst-compiled IJobChunk that iterates chunks containing LaneFlow components, applies time-weighted interpolation between existing m_Duration/m_Distance and m_Next, and clears m_Next. Runs in parallel.

  • Nested job: UpdateRoadFlowJob.Execute(in ArchetypeChunk chunk, ...)
    Burst-compiled IJobChunk that iterates Road chunks and their SubLane buffers, aggregates lane flows into per-road accumulators, computes flow speeds via NetUtils, updates CarLane.m_FlowOffset when flow offset changes (and records whether a lane is a roundabout), and enqueues FlowActionData via a NativeQueue.ParallelWriter for changed lanes.

  • Nested job helper: UpdateRoadFlowJob.UpdateLaneFlow(Entity lane, float4 flowSpeed, out bool isRoundabout)
    Checks if a lane has a CarLane component and, if so, computes a new flow offset byte based on the dot product of flowSpeed and the time factors. If changed, updates CarLane and enqueues a FlowActionData.

Usage Example

[Preserve]
protected override void OnCreate()
{
    base.OnCreate();
    m_SimulationSystem = base.World.GetOrCreateSystemManaged<SimulationSystem>();
    m_PathfindQueueSystem = base.World.GetOrCreateSystemManaged<PathfindQueueSystem>();
    m_TimeSystem = base.World.GetOrCreateSystemManaged<TimeSystem>();
    m_LaneQuery = GetEntityQuery(ComponentType.ReadWrite<LaneFlow>(), ComponentType.ReadOnly<UpdateFrame>(), ComponentType.Exclude<Deleted>(), ComponentType.Exclude<Temp>());
    m_RoadQuery = GetEntityQuery(ComponentType.ReadWrite<Road>(), ComponentType.ReadOnly<SubLane>(), ComponentType.ReadOnly<UpdateFrame>(), ComponentType.Exclude<Deleted>(), ComponentType.Exclude<Temp>());
    RequireAnyForUpdate(m_LaneQuery, m_RoadQuery);
}

Notes and implementation details: - The system is optimized for parallel execution using Burst and IJobChunk, but it also uses ComponentLookup and BufferLookup access patterns to safely read/write components. - Time-of-day weighting is computed into a float4 and used both for interpolation speed (UpdateLaneFlowJob) and for flow offset calculation (UpdateRoadFlowJob.UpdateLaneFlow). - Flow changes are not applied directly to pathfinding here; instead FlowActionData items are enqueued to PathfindQueueSystem for further processing. This decouples computation from path update application and allows batching. - UPDATES_PER_DAY and SimulationUtils.GetUpdateFrame are used to distribute updates across frames (so not all lanes/roads are updated each frame).