Traffic Manager System
Overview
The Traffic Manager is the central orchestrator for all NPC vehicle simulation. It manages multiple traffic simulators, controls spawn rate and density, enforces ego-vehicle safety distances, and handles the full lifecycle of NPC vehicles — from instantiation to despawn.
Core Architecture
graph TD
TM[TrafficManager] --> RTS[RandomTrafficSimulator ×N]
TM --> ROTS[RouteTrafficSimulator ×N]
TM --> NS[NPCVehicleSimulator]
NS --> COG[Cognition Step]
NS --> DEC[Decision Step]
NS --> CTR[Control Step]
NS --> VIS[Visualization Step]
TM --> TSC[TrafficSpawnConfig]
TSC --> JSON[(traffic_spawn.json)]
System Components
The manager supports two simulator types running simultaneously:
- RandomTrafficSimulator — spawns vehicles randomly across a set of lanes, with optional per-lane rates and branch weights. See Random Traffic.
- RouteTrafficSimulator — spawns vehicles that follow a fixed multi-lane route.
Both implement ITrafficSimulator, giving the manager a uniform interface for spawn requests.
The core physics engine that steps all active NPC vehicles each FixedUpdate:
graph LR
A[Cognition] --> B[Decision]
B --> C[Control]
C --> D[Visualization]
The pipeline runs burst-compiled parallel jobs for the cognition step, enabling real-time simulation of 40+ vehicles.
A static configuration layer loaded from Assets/Configs/traffic_spawn.json. It provides per-lane spawn rates and weighted branch probabilities to both TrafficManager and the lane-change logic. See TrafficSpawnConfig.
Inspector Reference
NPC Vehicle Settings
| Field | Default | Description |
|---|---|---|
vehicleConfig |
See below | Motion parameters for all NPC vehicles |
vehicleLayerMask |
— | Layer for vehicle-to-vehicle raycasting |
groundLayerMask |
— | Layer for ground-following raycasts |
maxVehicleCount |
40 | Maximum simultaneous NPC vehicles |
spawnDistanceToEgo |
50 m | Minimum distance from ego vehicle to any spawn point |
egoVehicle |
— | Reference to the ego. If unset, a dummy is created automatically. |
Spawn Config
| Field | Default | Description |
|---|---|---|
spawnConfigPath |
Assets/Configs/traffic_spawn.json |
Path to load/save spawn rates and branch weights |
Debug
| Field | Description |
|---|---|
showGizmos |
Master toggle for all debug gizmos |
showYieldingPhase |
Visualise intersection yield states |
showObstacleChecking |
Visualise obstacle detection rays |
showSpawnPoints |
Draw cyan cubes at all spawn lane starts |
NPCVehicleConfig Parameters
| Parameter | Default | Description |
|---|---|---|
Acceleration |
3 m/s² | Normal forward acceleration |
Deceleration |
2 m/s² | Gentle braking |
SuddenDeceleration |
4 m/s² | Obstacle braking |
AbsoluteDeceleration |
20 m/s² | Physics-limit emergency braking |
SpeedLimitSource |
FixedSpeedLimit |
LaneletSpeedLimit or FixedSpeedLimit |
FixedSpeedLimit |
13.89 m/s (50 km/h) | Used when source is Fixed |
Spawn Configuration (JSON)
TrafficManager can save and load a JSON file that controls per-lane spawn rates and branch weights. This makes it easy to tune traffic density without reopening the Unity Editor.
Context Menu Actions
Right-click on the TrafficManager component in the Inspector:
- Save Spawn Config JSON — writes current rates/weights from all simulators to the JSON file.
- Load Spawn Config JSON — reads the JSON file and applies it to all simulators.
The config is also loaded automatically at scene start if the file exists.
JSON Format
{
"spawnRates": [
{ "lane": "Lane_A1", "spawnsPerMinute": 6.0 },
{ "lane": "Lane_B2", "spawnsPerMinute": 3.5 }
],
"branchWeights": [
{
"fromLane": "Lane_A1",
"next": [
{ "lane": "Lane_B1", "weight": 2.0 },
{ "lane": "Lane_B2", "weight": 1.0 }
]
}
]
}
- Lane names are case-insensitive.
spawnsPerMinute = 0disables rate limiting for that lane.- Weights are normalised automatically; only ratios matter.
Per-Lane Rate Limiting
When a spawn rate is set for a lane, TrafficManager tracks the last spawn time per lane and skips spawn attempts until the interval has elapsed:
RemoveVehiclesInRadius
The Teleporter calls this method before moving the ego vehicle to its new spawn position. All NPC vehicles within radius metres of center are marked for despawn and removed on the next FixedUpdate.
// By world position
int count = trafficManager.RemoveVehiclesInRadius(position, radius);
// By transform
int count = trafficManager.RemoveVehiclesInRadius(transform, radius);
Returns the number of vehicles removed.
Simulation Pipeline
Fixed Update Cycle
sequenceDiagram
participant TM as TrafficManager
participant TS as Traffic Simulators
participant NS as NPCVehicleSimulator
TM->>TS: GetRandomSpawnInfo() for each simulator
TS-->>TM: spawnPoint + prefab
TM->>TM: Group by spawn point
TM->>TM: Filter: ego proximity check
TM->>TM: Filter: per-lane rate limit
TM->>TM: Collision check (IsSpawnable)
TM->>NS: Register new vehicle
TM->>NS: StepOnce(deltaTime)
NS->>NS: Cognition → Decision → Control → Visualization
TM->>TM: Despawn marked vehicles
Spawn Decision Logic
graph TD
A[Spawn request] --> B{Distance to ego ≥ 50m?}
B -- No --> SKIP[Skip this frame]
B -- Yes --> C{Rate limit elapsed?}
C -- No --> SKIP
C -- Yes --> D{Single simulator on lane?}
D -- Yes --> E[IsSpawnable check]
D -- No --> F[Priority sort → highest wins]
F --> E
E -- Clear --> G[Spawn vehicle]
E -- Blocked --> SKIP
NPC Vehicle Simulation Pipeline
Step 1 — Cognition
Runs as burst-compiled parallel jobs. Each vehicle gathers:
- Ground existence (vehicle must be above valid surface)
- Next lane and waypoint
- Traffic light state and passability
- Right-of-way at intersections
- Curve detection (upcoming sharp turns → reduce speed)
- Front obstacle distance
Step 2 — Decision
Determines each vehicle's immediate action:
| Speed Mode | Trigger |
|---|---|
NORMAL |
Open road, green light |
SLOW |
Approaching curve or distant obstacle |
STOP |
Red light, pedestrian crossing, intersection yield |
SUDDEN_STOP |
Close obstacle, blocked crossing |
ABSOLUTE_STOP |
Emergency physics limit |
The decision step also checks ZebraCrossingArea.TryGetBlockedStop() to yield to pedestrians at crosswalks. See Zebra Crossing.
Step 3 — Control
Updates vehicle kinematics:
- Speed adjusted toward target via acceleration/deceleration ramp
- Steering computed from angle to next waypoint
- Position and rotation applied to the Unity transform
Step 4 — Visualization
- Applies computed transform to the NPC GameObject
- Updates turn signal state based on upcoming lane
Traffic Light Integration
Follows the Vienna Convention:
| State | NPC Behaviour |
|---|---|
| 🟢 Green | Proceed normally |
| 🟡 Yellow | Stop if distance allows; otherwise commit |
| 🔴 Red | Stop at stop line |
Yellow light decision:
if distance_to_light < sudden_stop_distance:
commit (cannot stop safely)
else:
stop
Intersection Right-of-Way
NPC vehicles use a yield phase system at intersections:
| Phase | Meaning |
|---|---|
ENTERING_INTERSECTION |
Evaluating whether to yield |
LEFT_HAND_RULE_ENTERING |
Yielding to right-hand traffic |
LANES_RULES_ENTERING |
Yielding based on configured lane priorities |
INTERSECTION_BLOCKED |
Waiting because cross traffic is present |
FORCING_PRIORITY |
Override to break a deadlock |
Lifecycle Management
Initialization (Start)
graph TD
A[Start] --> B[Load spawn config JSON if exists]
B --> C[Create NPCVehicleSimulator]
C --> D[verifyIntegrationEnvironmentElements]
D --> E[Instantiate RandomTrafficSimulators]
E --> F[Instantiate RouteTrafficSimulators]
F --> G[Set up ego vehicle reference]
Restart
trafficManager.Restart(newMaxVehicleCount: 20);
Disposes all current state, re-runs initialization with the new parameters.
Destroy
On OnDestroy, the manager calls TrafficSpawnConfig.ExportBranchDecisionCsv() to write the full branch decision statistics to Assets/Configs/traffic_branch_decisions.csv. See TrafficSpawnConfig for the CSV format.
Scene Setup Checklist
Required before Play
- [ ] A GameObject named
TrafficLanesexists in the scene. - [ ] All
TrafficLanechild objects have unique names. - [ ] At least one
TrafficLanehasintersectionLane = true. - [ ]
TrafficManager.vehicleLayerMaskandgroundLayerMaskare assigned. - [ ] At least one
RandomTrafficSimulatorConfigurationentry is configured.
These are validated at startup. Errors appear in the Console with descriptive messages.
Extensibility
Custom simulators can be added at runtime via:
trafficManager.AddTrafficSimulator(new MyCustomSimulator(...));
Any class implementing ITrafficSimulator integrates automatically with the priority system and spawn loop.