Traffic Car
How To Create
Create a vehicle using the Car Prefab Creator tool (for example Simple physics entity type, if you need traffic with controller based on MonoBehaviour, read this article).
Car Prefab Creator final step example.
Make sure, that the vehicle collection contains vehicle you have created.
Make sure, that the preset contains the vehicle.
Open the Traffic settings and select the Simple physics entity type (if you have created a Simple physics entity).
Open the Hub object in the scene and press the Copy To Subscene button.
Open the EntitySubScene, find the TrafficCarEntityPoolBakerRef gameobject on the main & subscene, make sure the correct preset is assigned to both scenes.
- Adjust the traffic settings of the created vehicles.
For Simple physics.
For Custom physics.
Vehicle Physics Types
Custom Physics
Entities that are moved by the custom physical system.
Hybrid Entity Custom Physics & Pure Entity Custom Physics types refer to this.
Simple Physics
Entities moved by the simple physical system (by simply adding the physics velocity to the physics body).
Hybrid entity simple physics & Pure entity simple physics types refer to this.
Authoring components
PhysicsBody
PhysicsShape
![]()
Example
Optional components if the car moves with physics.
No Physics
Pure entities that moved by transform system without physics.
Contains the same components as Simple Physics.
Pure entity no physics type refer to this.
Hybrid Mono
Before using this vehicle type, make sure that you selected World simulation type to Hybrid mono in the General settings.
Hybrid entities that moved by custom monobehaviour controller.
Hybrid entity mono physics type refer to this.
Arcade (built-in sample)
If you want to use Arcade’s built-in sample controller, follow these steps:
Open the Car Prefab Creator tool.
Select Prefab tab.
Set Car type to Traffic.
Drag & drop your prefabs into the prefabs field (make sure your source Prefabs don’t have any Colliders, Wheel colliders & Rigidbodies).
Press Scan button.
Select Save tab.
Set Entity type to Hybrid entity mono physics.
Set Controller type to Arcade.
Set desired preset. Also hull & save paths.
Select Prefab info tab.
Customize hull & wheel offsets.
Customize traffic related settings.
Press Create button.
In the ArcadeVehicleController, make sure the raycast layer matches your Ground layer.
Open the EntitySubScene, find the TrafficCarEntityPoolBakerRef gameobject on the main & subscene, make sure the correct preset is assigned to both scenes.
Custom user controller
If you want to use your own custom solution, follow these steps:
Open the Car Prefab Creator tool.
Select Prefab tab.
Set Car type to Traffic.
Drag & drop your prefabs into the prefabs field.
Press Scan button.
Select Save tab.
Set Entity type to Hybrid entity mono physics.
Set Controller type to Custom user.
Create script that implements IVehicleInput interface to link traffic input & your vehicle controller input (code example below)
Assign created script into the Input script field.
Set desired preset. Also hull & save paths.
Select Prefab info tab.
Set the steering angle to match the steering of your custom car controller.
Customize traffic related settings.
Press Create button.
To set your own custom Car Controller parameters to handle the most common traffic situations, use the Traffic test scene.
Open the EntitySubScene, find the TrafficCarEntityPoolBakerRef gameobject on the main & subscene, make sure the correct preset is assigned to both scenes.
Input info
Throttle [1] : forward motion.
Throttle [-1] : reverse motion.
Throttle [0] : hand brake.
Throttle [-0.9] : braking, for example, if the current speed is higher than permitted. (the value can be changed in the Traffic settings)
Steering [-1, 1]
VehicleInput example code
public class UVC_adapter : MonoBehaviour, IVehicleInput { // Replace by your custom controller script. // The example uses a "Universal Vehicle Controller". // https://assetstore.unity.com/packages/tools/physics/universal-vehicle-controller-plus-176314 public UVC_AIControl carControllerInput; public float Throttle { get => carControllerInput.Acceleration; set { if (value > 0) { carControllerInput.SetAcceleration(value); carControllerInput.SetBrakeReverse(0); carControllerInput.SetHandBrake(false); } else { carControllerInput.SetAcceleration(0); carControllerInput.SetBrakeReverse(Mathf.Abs(value)); if (value == 0) carControllerInput.SetHandBrake(true); } } } public float Steering { get => carControllerInput.Horizontal; set => carControllerInput.SetSteer(value); } public bool Handbrake { get => carControllerInput.HandBrake; set => carControllerInput.SetHandBrake(value); } public void SwitchEnabledState(bool isEnabled) { carControllerInput.enabled = isEnabled; } }
Components
CarEntityAdapter
Component to syncronize gameobject & entity, also to switch physics & scripts of the vehicle when cull state changes with PhysicsSwitcher & ScriptSwitcher components.
Note
You can turn off traffic physics culling in the Traffic settings.
PhysicsSwitcher
Component to on/off physics of the vehicle.
ScriptSwitcher
Component to on/off scripts of the vehicle.
CullState Info
States
Culled : entity is destroyed.
- CloseToCamera:
Cull physics (if enabled) : custom physics & simple physics temporarily converted to no physics entity.
Cull wheel (if enabled) : disabling wheel rotating.
InVisionOfCamera : entity fully enabled.
Avoidance
- Currently enabled in the following situations:
A cyclical obstacle where cars get stuck in each other (avoidance config).
A car has collided frontally with another car (collision config).
Cyclical obstacle example.
Avoiding cyclical obstacle example.
Note
Test scene example.
Entity Selection
Entity can be retrieved using one of these methods:
Pure DOTS
Create a new gameobject with EntitySelectionService component
Use world position to get the nearest entity for that position.
public Entity TryToSelectEntity(Vector3 worldPosition) { return EntitySelectionService.Instance.SelectEntity(worldPosition, EntityType.Traffic, 1f); }
Hybrid Mono
Entity can be retrieved if the car has a collider:
private Entity GetEntity() { Entity entity = Entity.Null; if (Physics.Raycast(transform.position, Vector3.forward, out hit, 1.0f)) { var hybridEntityRef = hit.collider.GetComponent<IHybridEntityRef>(); entity = hybridEntityRef.RelatedEntity; } return entity; }
Rail Movement
The Rail movement is used to drive the vehicle precisely along the path, which can be useful in small enclosed parking areas, for example. To enable rail movement, tick on the Rail parameter in the path settings. Open the rail config to adjust the Rail parameters (DOTS only).
Note
Enabled by default for trams.
Obstacle Detection
Raycast
Config
Debugger
Modes
Hybrid mode : raycast is activated only when the selected targets are close to the car.
Raycast only : raycasts are sent constantly.
To define raycast targets for Hybrid or Raycast only modes, redefine the GetTargetQuery method in the TrafficCarRaycastObstacleTargetQueryProvider class, which returns the EntityQuery of the targets.
public static EntityQuery GetTargetQuery(
SystemBase sourceSystem,
TrafficCarDetectObstacleMode trafficCarDetectObstacleMode,
TrafficCarDetectNpcMode trafficCarDetectNpcMode,
out CollisionFilter tempRaycastCollisionFilter,
out CollisionFilter raycastAlwaysCollisionFilter);
Hybrid Mode Filter : collision filter of hybrid raycast mode.
Raycast Only Filter : collision filter of raycast only mode.
Note
You can also dynamically change the raycast target for Hybrid mode by adding or removing the TrafficCustomRaycastTargetTag component.
Layer constants are stored in the ProjectConstants.cs file.
Obstacle Avoidance
If you want the traffic to avoid obstacles, follow these steps:
Make sure that obstacle detection is set to either Hybrid or Raycast in the Traffic config.
Ensure that Advanced avoidance is enabled in the Collision config.
Make sure that the traffic Raycast config includes an obstacle layer.
Add components to the obstacle object from the example below, depending on the type of obstacle.
Player Character
![]()
Note
Make sure that Player Npc Hybrid Component is removed.
Player Car
Dynamic Obstacle
Static Obstacle
Left-hand Drive
To make the traffic left-hand drive:
Find & open
ProjectConstantsscript.Change the
LaneHandDirectionvariable to-1.Note
Changing this parameter will only affect newly created scenes. Old scenes with a different lane direction will not work.
Pathfinding
Custom Point
To set a custom destination for a specific traffic car, do the following:
Create a new gameobject with
EntitySelectionServicecomponent.Create a new gameobject with
TrafficCustomPathServicecomponent.Use this sample code:
private void Awake() { PathHashMapSystem.Register(); } public void SetEntity(Vector3 trafficPosition, Vector3 destination) { var trafficEntity = EntitySelectionService.Instance.SelectEntity(trafficPosition, EntitySelectionService.EntityType.Traffic, 2f); TrafficCustomPathService.Instance.SetFollowPath(trafficEntity, destination); }
Use the
OnStatusUpdatedcallback inTrafficCustomPathServiceto listen to the current state of the traffic car’s pathfinding.
Custom Node
To set a custom node destination for a specific traffic car, do the following:
Create a new gameobject with
EntitySelectionServicecomponent.Create a new gameobject with
TrafficCustomPathServicecomponent.Use this sample code:
private void Awake() { PathHashMapSystem.Register(); } public void SetEntity(Vector3 trafficPosition, Vector3 destination) { var trafficEntity = EntitySelectionService.Instance.SelectEntity(trafficPosition, EntitySelectionService.EntityType.Traffic, 2f); var destinationPath = PathHashMapSystem.GetClosestPath(destination); TrafficCustomPathService.Instance.SetFollowPath(trafficEntity, destinationPath); }
Use the
OnStatusUpdatedcallback inTrafficCustomPathServiceto listen to the current state of the traffic car’s pathfinding.As an alternative, you can check the
TrafficPathSelectorprefab for an interactive user-selected path used in the RuntimeTileRoad Demo scene (runtime sample should be imported & RUNTIME_ROAD scripting define added).