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).