PhysX Vehicle scripting and control

Address every public vehicle bus with the chassis entity id. Control and state buses are reflected to BehaviorContext (Lua / Script Canvas category PhysX Vehicle). Notification events are C++-only in the shipped Gem.

Who writes input

PhysX Vehicle Drive ──┐
Lua / Script Canvas ──┼──► VehicleControlRequestBus ──► Chassis solver
C++ / AI ──┘

Use one owner for throttle / steer / brake each frame. If Drive and a script both write the control bus, the last writer wins.

VehicleControlRequestBus

MethodRange / notes
SetThrottle[0, 1]
SetBrake[0, 1]
SetSteer[-1, 1] (left negative, right positive)
SetHandbrakebool
SetGearreverse < 0, neutral 0, forward > 0
SetTrackThrottle(left, right)Tracked; typically [-1, 1] scaled to max track speed; no-op on wheeled

C++:

#include <PhysXVehicle/VehicleControlBus.h>

PhysXVehicle::VehicleControlRequestBus::Event(
 chassisEntityId, &PhysXVehicle::VehicleControlRequests::SetGear, 1);
PhysXVehicle::VehicleControlRequestBus::Event(
 chassisEntityId, &PhysXVehicle::VehicleControlRequests::SetThrottle, 1.0f);
PhysXVehicle::VehicleControlRequestBus::Event(
 chassisEntityId, &PhysXVehicle::VehicleControlRequests::SetSteer, -0.25f);

Lua (BehaviorContext):

VehicleControlRequestBus.Event.SetGear(self.entityId, 1)
VehicleControlRequestBus.Event.SetThrottle(self.entityId, 1.0)
VehicleControlRequestBus.Event.SetBrake(self.entityId, 0.0)
VehicleControlRequestBus.Event.SetSteer(self.entityId, 0.0)
VehicleControlRequestBus.Event.SetHandbrake(self.entityId, false)

Tracked differential:

PhysXVehicle::VehicleControlRequestBus::Event(
 chassisEntityId, &PhysXVehicle::VehicleControlRequests::SetTrackThrottle,
 leftThrottle, rightThrottle);

VehicleStateRequestBus

MethodReturns
GetSpeedForward speed along vehicle forward, m/s
GetEngineRpmEngine RPM from driven wheels
GetCurrentGearCurrent gear (same sign convention as SetGear)
IsWheelGrounded(wheelIndex)Contact this step
GetWheelSuspensionCompression(wheelIndex)Compression, m
GetWheelAngularVelocity(wheelIndex)Spin, rad/s
GetWheelCountConfigured wheel count
GetTrackSurfaceSpeedLeft / RightTracked commanded surface speed, m/s (else 0)
GetTrackTravelDistanceLeft / RightAccumulated travel, m, for UV scroll (else 0)
#include <PhysXVehicle/VehicleStateBus.h>

float speed = 0.0f;
PhysXVehicle::VehicleStateRequestBus::EventResult(
 speed, chassisEntityId, &PhysXVehicle::VehicleStateRequests::GetSpeed);
local speed = VehicleStateRequestBus.Event.GetSpeed(self.entityId)
local rpm = VehicleStateRequestBus.Event.GetEngineRpm(self.entityId)
local gear = VehicleStateRequestBus.Event.GetCurrentGear(self.entityId)

VehicleNotificationBus (C++ only)

EventMeaning
OnWheelGroundedChanged(wheelIndex, grounded)Wheel contact transition
OnGearChanged(newGear)Active gear changed
OnVehicleAirborne(airborne)All wheels left / regained ground

These handlers are not reflected to BehaviorContext. Subscribe from C++ with VehicleNotificationBus::Handler on the chassis entity. For scripted reactions, poll state on tick or bridge through your own gameplay component.

Sample Lua driver

Gems/PhysXVehicle/Assets/Scripts/VehicleDriveExample.lua:

  • Attach a Lua Script component to the chassis entity.
  • Maps StartingPointInput (or Input Bindings) events:
  • vehicle_throttle analog [0, 1]
  • vehicle_brake analog [0, 1]
  • vehicle_steer analog [-1, 1]
  • vehicle_handbrake digital
  • Calls SetGear(1) on activate and optionally logs speed / RPM / gear each second.

Disable PhysX Vehicle Drive when using this script so inputs do not fight.

Script Canvas

Look for EBus nodes under category PhysX Vehicle:

  • Request nodes for each Set* / Get* on Control and State.
  • Wire entity id pins to the chassis entity.

There are no Script Canvas event nodes for VehicleNotificationBus in the shipped Gem.

AI and gameplay

Typical pattern:

  1. Omit Drive (or set Enabled = false).
  2. Each AI tick (or decision), write throttle / steer / brake / gear (or SetTrackThrottle).
  3. Read GetSpeed / grounded flags for decisions.
  4. Optionally sync track UV from travel distances in a visual component.

Configuration structs are not exposed as a live script API—author them in the editor / Prefab.

Next steps


Copyright © 2026 DawnEngine. All rights reserved.

DawnEngine is a commercial 3D engine distributed under the DawnEngine end-user license agreement. Engine binaries and source are proprietary and are not covered by the licenses below.

Documentation only: the prose and templates on this site are a derivative work of Open 3D Engine (O3DE) documentation by the O3DE Contributors, used under CC BY 4.0 (documentation content), Apache 2.0 (site code), and the MIT license (inline code samples).

The open-source 3D engine that DawnEngine is built on top of is Open 3D Engine . DawnEngine is not affiliated with, endorsed by, or sponsored by The Linux Foundation or the O3DE project. “O3DE” and “Open 3D Engine” are trademarks of The Linux Foundation.