Game.TrafficBottleneckSystem
Assembly:
Namespace: Game.Simulation
Type: class
Base: GameSystemBase
Summary:
TrafficBottleneckSystem analyzes vehicle "blocker" relationships at the end of each update interval to detect traffic bottlenecks on lanes. It groups entities that are blocking each other, determines whether a group constitutes a bottleneck (and whether an existing bottleneck should be kept or removed), and adds/removes/updates Bottleneck components and UI icon notifications accordingly. The heavy work runs inside a Burst-compiled IJob (TrafficBottleneckJob) using chunked entity queries, Native containers and deferred command buffers (IconCommandBuffer and EndFrameBarrier/EntityCommandBuffer). The job also enqueues a TriggerAction reporting the number of active bottlenecks.
Fields
-
private IconCommandSystem m_IconCommandSystem
Holds the IconCommandSystem instance used to create IconCommandBuffer writers for adding/removing UI icons for bottlenecks. -
private TriggerSystem m_TriggerSystem
Holds the TriggerSystem instance used to create an action buffer to enqueue TriggerAction events (TriggerType.TrafficBottleneck). -
private EndFrameBarrier m_EndFrameBarrier
Used to create an EntityCommandBuffer for deferred structural changes (adding/removing components) produced by the job. -
private EntityQuery m_BlockerQuery
EntityQuery that selects entities with Blocker and Vehicle components (excluding Deleted and Temp). These are the "blocker" entities used to form groups. -
private EntityQuery m_BottleneckQuery
EntityQuery that selects entities with Bottleneck components (excluding Deleted). Used to iterate existing bottlenecks and update timers/visibility. -
private EntityQuery m_ConfigurationQuery
EntityQuery used to fetch the singleton TrafficConfigurationData which holds bottleneck notification prefab id and other settings. -
private TypeHandle __TypeHandle
Cached helper struct containing EntityTypeHandle, ComponentTypeHandles and ComponentLookup handles used to build the TrafficBottleneckJob.
(Nested helper types in this class: GroupData, BottleneckData, BottleneckState, TrafficBottleneckJob, TypeHandle — see summary for role.)
Properties
- (none)
Constructors
public TrafficBottleneckSystem()
Default constructor. The class uses [Preserve] on lifecycle methods and constructor to prevent stripping. Initialization of system state is done in OnCreate.
Methods
-
public override int GetUpdateInterval(SystemUpdatePhase phase)
Returns 64. This system is intended to run at an interval (every 64 ticks/frames) rather than every frame. -
[Preserve] protected override void OnCreate()
Initializes references to dependent systems (IconCommandSystem, TriggerSystem, EndFrameBarrier) and sets up EntityQueries: - m_BlockerQuery: Blocker + Vehicle (exclude Deleted, Temp)
- m_BottleneckQuery: Bottleneck (exclude Deleted)
-
m_ConfigurationQuery: TrafficConfigurationData singleton Also calls RequireAnyForUpdate(m_BlockerQuery, m_BottleneckQuery) so the system only runs when relevant data exists.
-
[Preserve] protected override void OnUpdate()
Builds chunk lists for blockers and bottlenecks asynchronously, constructs and schedules the Burst-compiled TrafficBottleneckJob with combined dependencies. The job: - Fills a map of existing bottlenecks (marking them Remove by default).
- Forms groups of mutual blockers using Blocker.m_Blocker references (union-find-like merging).
- For groups above a configured size threshold, decides to Keep or Add bottlenecks based on group size and blocker types.
- Updates or adds Bottleneck components (with min/max ranges and positions) and manages Bottleneck.m_Timer values to fade in/out notifications.
-
Adds/removes icon notifications via IconCommandBuffer and enqueues a TriggerAction with the count of active bottlenecks. OnUpdate also wires job dependencies to m_IconCommandSystem and m_EndFrameBarrier and disposes temporary chunk lists after the job.
-
protected override void OnCreateForCompiler()
Compiler helper used by source-generated systems: assigns queries and type handles for the job. -
private void __AssignQueries(ref SystemState state)
Internal/inline helper (generated pattern) for query assignment. In this class it is effectively a placeholder called from OnCreateForCompiler.
(Implementation detail — TrafficBottleneckJob (Burst compiled) contains the core algorithms:
- Uses NativeParallelHashMap
Usage Example
[Preserve]
protected override void OnCreate()
{
base.OnCreate();
m_IconCommandSystem = base.World.GetOrCreateSystemManaged<IconCommandSystem>();
m_TriggerSystem = base.World.GetOrCreateSystemManaged<TriggerSystem>();
m_EndFrameBarrier = base.World.GetOrCreateSystemManaged<EndFrameBarrier>();
m_BlockerQuery = GetEntityQuery(
ComponentType.ReadOnly<Blocker>(),
ComponentType.ReadOnly<Vehicle>(),
ComponentType.Exclude<Deleted>(),
ComponentType.Exclude<Temp>());
m_BottleneckQuery = GetEntityQuery(
ComponentType.ReadOnly<Bottleneck>(),
ComponentType.Exclude<Deleted>());
m_ConfigurationQuery = GetEntityQuery(
ComponentType.ReadOnly<TrafficConfigurationData>());
RequireAnyForUpdate(m_BlockerQuery, m_BottleneckQuery);
}
Notes and tips for modders: - The system runs infrequently (GetUpdateInterval => 64) to reduce cost; changing that value will affect performance and detection responsiveness. - Bottleneck additions/removals are done via an EndFrameBarrier EntityCommandBuffer to avoid structural changes inside the job. - Icon commands are issued via IconCommandSystem; to change the notification prefab or behavior, edit TrafficConfigurationData or intercept IconCommandBuffer usage. - The grouping logic merges blocker relationships transitively; groups with >=10 members are considered for bottleneck creation. The threshold is hard-coded in the job (groupData.m_Count >= 10) and groupData.m_Count < 50 influences whether a Keep vs Add decision is made. Adjusting detection thresholds requires modifying the job code.