Physics and navigation¶
Rigid bodies, colliders, characters, joints, vehicles, world settings and navigation.
body¶
Simulated rigid body (Jolt). dynamic = moved by forces and collisions, kinematic = moved by its transform (platforms, doors) and pushes dynamic bodies, static = never moves. Needs no collider: the shape is fitted to the mesh. Child entities with a collider (and no body of their own) become parts of this body.
| Field | Type | Description | Values |
|---|---|---|---|
motion |
string | How the body moves | dynamic static kinematic |
mass |
number | Mass in kg (crate 20, person 70, car 1200) | 0.001 .. 10000000 |
friction |
number | Surface friction (ice 0.05, wood 0.5, rubber 1) | 0 .. 10 |
restitution |
number | Bounciness: 0 = no bounce, 1 = perfectly elastic | 0 .. 1 |
linearDamping |
number | Air drag on movement | 0 .. 100 |
angularDamping |
number | Drag on spinning | 0 .. 100 |
gravityScale |
number | Gravity multiplier (0 = floats, -1 = falls up) | -100 .. 100 |
lockPosition |
string | World axes along which the body cannot move ("z" for 2D games) | none x y z xy xz yz xyz |
lockRotation |
string | World axes around which the body cannot rotate ("xz" stays upright) | none x y z xy xz yz xyz |
ccd |
boolean | Continuous collision detection: fast objects never tunnel through walls | |
startAwake |
boolean | Simulate from the start (false = sleep until touched) | |
velocity |
number[3] | Linear velocity m/s (initial; live while playing, writable) | |
angularVelocity |
number[3] | Angular velocity in degrees/s (initial; live while playing) | |
layer |
string | Collision layer (which layers collide: physics_world.ignorePairs) | default static player enemy projectile trigger debris |
collider¶
Collision shape. Alone it makes static geometry (walls, floors); with a body it shapes the body. auto fits the mesh (box/sphere/capsule/cylinder for primitives, convex hull for dynamic models, triangle mesh for static models). mesh = exact triangles (static/kinematic only); convex = hull of the mesh; heightfield = terrain. isTrigger makes a sensor zone that fires on trigger_enter / on trigger_exit instead of blocking.
| Field | Type | Description | Values |
|---|---|---|---|
shape |
string | Shape type | auto box sphere capsule cylinder convex mesh heightfield |
size |
number[3] | Box: full size (local units); heightfield: x/z extent, y = max height | |
radius |
number | Sphere/capsule/cylinder radius (local units) | 0.001 .. 100000 |
height |
number | Capsule/cylinder total height along local Y | 0.001 .. 100000 |
offset |
number[3] | Shape center relative to the entity origin (local) | |
rotation |
number[3] | Shape rotation relative to the entity (Euler degrees) | |
isTrigger |
boolean | Sensor: detects overlaps (trigger_enter/exit) but never blocks | |
friction |
number | Material friction override (-1 = use the body's) | -1 .. 10 |
restitution |
number | Material bounciness override (-1 = use the body's) | -1 .. 1 |
heightmap |
string | Heightfield source, project-relative: 16-bit .r16/.raw (square) or .hdr; empty = sample the mesh | |
resolution |
integer | Heightfield samples per side (8..1024) |
character¶
Capsule character controller: walks up slopes and stairs, slides along walls, rides moving platforms, pushes dynamic bodies and is detected by triggers. Drive it from Wander every tick: walk(self, dir), jump(self), grounded(self). Units are meters (not scaled by the transform).
| Field | Type | Description | Values |
|---|---|---|---|
height |
number | Capsule height in m | 0.1 .. 50 |
radius |
number | Capsule radius in m | 0.05 .. 10 |
offset |
number[3] | Capsule center relative to the entity origin in m (y = height/2 for models with the origin at the feet) | |
maxSlope |
number | Steepest walkable slope in degrees | 0 .. 89 |
stepHeight |
number | Highest step/curb climbed automatically (m) | 0 .. 5 |
moveSpeed |
number | Walking speed in m/s for walk(self, dir) with |dir| = 1 | 0 .. 100 |
jumpSpeed |
number | Upward speed of jump() in m/s | 0 .. 100 |
gravity |
number | Downward acceleration in m/s^2 | 0 .. 200 |
airControl |
number | Steering while airborne (0 none .. 1 full) | 0 .. 1 |
turnSpeed |
number | Degrees/s to turn toward the walk direction (0 = off) | 0 .. 100000 |
pushStrength |
number | Max force in N used to push dynamic bodies | 0 .. 1000000 |
mass |
number | Mass in kg | 1 .. 100000 |
layer |
string | Collision layer | default static player enemy projectile trigger debris |
velocity |
number[3] | Current velocity m/s (live while playing; write for knockback) |
joint¶
Connects this entity's body to another body (target) or to the world. fixed = welded; hinge = doors, wheels, levers (axis, limits in degrees, motor); ball = chains, ragdoll shoulders; slider = pistons, drawers (axis, limits in m); distance = rope/rod (limits = min/max length); spring = bouncy link (stiffness Hz, damping). Breaks above breakForce (fires on event "joint_broken" on this entity).
| Field | Type | Description | Values |
|---|---|---|---|
kind |
string | Joint type | fixed hinge ball slider distance spring |
target |
object | string | integer | null | Other entity (name, #id or {"id"}); empty = attached to the world — entity link: name ("Door"), "#id", {"id": 12} or null; read back as {"id", "name"} (follows renames; entity_refs lists links) | |
anchor |
number[3] | Pivot point in this entity's local space | |
connectedAnchor |
number[3] | distance/spring: the other end in the target's local space (a world point when attached to the world) | |
axis |
number[3] | Hinge axis / slider direction in local space | |
limitMin |
number | Lower limit: degrees (hinge), m (slider, distance); used when min < max | |
limitMax |
number | Upper limit | |
motorSpeed |
number | Motor target speed: degrees/s (hinge) or m/s (slider) | |
motorForce |
number | Motor max torque (N m) or force (N); 0 = no motor | 0 .. 1000000000 |
stiffness |
number | Spring frequency in Hz (spring joints) | 0 .. 1000 |
damping |
number | Spring damping ratio (0 = bouncy, 1 = critically damped) | 0 .. 100 |
breakForce |
number | Breaks when the joint force exceeds this (N); 0 = unbreakable | 0 .. 999999995904 |
collideConnected |
boolean | Let the two connected bodies collide with each other | |
enabled |
boolean | Active (set to false when the joint breaks) |
vehicle¶
Drivable wheeled vehicle (Jolt vehicle constraint): suspension, tire friction curves, engine torque curve, auto/manual gearbox, FWD/RWD/AWD limited-slip differentials, anti-roll bars, downforce and drag. Needs a dynamic body on the same entity (the chassis). Child entities named wheel* are the wheels (fitted automatically when wheels is empty) and spin/steer/bounce while playing. Drive it with the inputs (throttle, brake, steer, handbrake): control=player reads the drive input actions, or set them from Wander (vehicle_drive(self, ...)). Build one with vehicle_create, tune by numbers with vehicle_tune + vehicle_test_drive, watch it with vehicle_info.
| Field | Type | Description | Values |
|---|---|---|---|
preset |
string | Preset it was built from (informational): sports, hatchback, truck, kart, custom | |
mass |
number | Chassis mass in kg (kart 160, hatchback 1150, sports 1350, truck 2600) | 1 .. 1000000 |
centerOfMass |
number[3] | Center-of-mass offset in m (local); lower y = less body roll, harder to flip | |
maxTilt |
number | Max pitch/roll in degrees before the chassis is held upright (180 = can flip) | 5 .. 180 |
wheels |
object[] | Per-wheel setup in chassis space; empty = fitted at play from children named wheel*. Any field overrides the vehicle default for that wheel | |
wheelRadius |
number | Wheel radius in m (0 = measured from the wheel meshes) | 0 .. 10 |
wheelWidth |
number | Wheel width in m (0 = measured) | 0 .. 10 |
suspensionMinLength |
number | Suspension length fully compressed (m below the mount) | 0 .. 5 |
suspensionMaxLength |
number | Suspension length fully extended (m below the mount) | 0.01 .. 5 |
suspensionFrequency |
number | Spring frequency in Hz (1 soft, 1.6 road, 2.5+ race) | 0.1 .. 20 |
suspensionDamping |
number | Damping ratio (0.3 floaty, 0.5 road, 1 stiff) | 0 .. 5 |
steering |
string | Which wheels steer | front rear all none |
maxSteerAngle |
number | Steering lock in degrees | 0 .. 89 |
brakeTorque |
number | Brake torque per wheel in N m at full brake | 0 .. 1000000 |
handbrakeTorque |
number | Handbrake torque per rear wheel in N m | 0 .. 1000000 |
longitudinalGrip |
number | Peak tire friction accelerating/braking (1 economy tires, 1.25 sports, 1.6 slicks) | 0 .. 10 |
lateralGrip |
number | Peak tire friction cornering: about the skidpad g (0.9 hatchback, 1.1 sports; lower = slides sooner) | 0 .. 10 |
longitudinalCurve |
number[2][] | Tire friction vs slip ratio [[slip, 0..1], ...] (scaled by longitudinalGrip); empty = default | |
lateralCurve |
number[2][] | Tire friction vs slip angle [[degrees, 0..1], ...] (scaled by lateralGrip); empty = default | |
drive |
string | Driven wheels | fwd rwd awd |
frontTorqueSplit |
number | AWD: share of the torque sent to the front axle | 0 .. 1 |
limitedSlip |
number | Limited-slip ratio of the differentials (1.4 tight, >= 10 open) | 1.01 .. 1000000 |
differentialRatio |
number | Final drive ratio | 0.1 .. 50 |
maxTorque |
number | Peak engine torque in N m | 0 .. 1000000 |
minRpm |
number | Idle rpm | 0 .. 30000 |
maxRpm |
number | Redline rpm | 100 .. 30000 |
engineInertia |
number | Engine inertia in kg m^2 (lower revs faster) | 0.01 .. 100 |
engineDamping |
number | Engine braking / internal friction | 0 .. 10 |
torqueCurve |
number[2][] | Torque vs rpm [[rpm fraction, torque fraction], ...]; empty = default | |
transmission |
string | Gearbox: auto shifts by rpm; manual uses vehicle_shift / shift actions | auto manual |
gearRatios |
number[] | Forward gear ratios, first gear first; empty = [2.66, 1.78, 1.3, 1.0, 0.74] | |
reverseRatio |
number | Reverse gear ratio (magnitude) | 0.1 .. 50 |
shiftUpRpm |
number | Auto gearbox shifts up above this rpm | 100 .. 30000 |
shiftDownRpm |
number | Auto gearbox shifts down below this rpm | 50 .. 30000 |
shiftTime |
number | Seconds without drive while shifting | 0 .. 5 |
clutchStrength |
number | Clutch coupling strength | 0.1 .. 1000 |
antiRollFront |
number | Front anti-roll bar (0 none, 300 soft, 700 sporty, 2000 very stiff; above ~4000 the body can shake) | 0 .. 20000 |
antiRollRear |
number | Rear anti-roll bar (stiffer than the front = more oversteer) | 0 .. 20000 |
downforce |
number | Aero downforce in N per (m/s)^2 (0.4 road car, 2+ race car) | 0 .. 1000 |
drag |
number | Aero drag in N per (m/s)^2 (limits top speed; ~0.5 * rho * Cd * area) | 0 .. 1000 |
control |
string | Who sets the inputs: player = drive input actions, script = Wander/tools, none | player script none |
steerSpeed |
number | Steering response: full lock per second (0 = instant) | 0 .. 100 |
speedSensitiveSteering |
number | Less steering lock at speed, 0..1 | 0 .. 1 |
tractionControl |
boolean | Traction control: limits wheelspin under throttle | |
abs |
boolean | Anti-lock brakes: keeps the wheels rolling (and steering) under hard braking | |
driftAssist |
number | Arcade drift help 0..1: easy slides that hold their angle | 0 .. 1 |
autoReverse |
boolean | Holding brake at a standstill reverses | |
engineAudio |
boolean | Drive the entity's audio component: pitch from rpm, volume from load | |
throttle |
number | Input: accelerator 0..1 (live) | 0 .. 1 |
brake |
number | Input: brake pedal 0..1 (live) | 0 .. 1 |
steer |
number | Input: steering -1 left .. 1 right (live) | -1 .. 1 |
handbrake |
number | Input: handbrake 0..1 (live) | 0 .. 1 |
gear |
integer | Current gear (-1 reverse, 0 neutral); manual gearbox: write to shift | |
speed |
number | Telemetry: km/h along the heading (negative reversing) | |
rpm |
number | Telemetry: engine rpm | |
wheelsOnGround |
integer | Telemetry: wheels touching the ground | |
skid |
number | Telemetry: strongest tire slide 0..1 (tire smoke, skid marks, squeal) |
chase_camera¶
Spring-arm chase camera: follows target from behind with look-ahead into corners, collision pull-in and a field of view that widens with speed. Put it on an entity with a camera (vehicle_create chase_camera=true sets it up). Moves every tick while playing.
| Field | Type | Description | Values |
|---|---|---|---|
target |
object | string | integer | null | Entity to follow (the vehicle) — entity link: name ("Door"), "#id", {"id": 12} or null; read back as {"id", "name"} (follows renames; entity_refs lists links) | |
distance |
number | Distance behind the target in m | 0 .. 1000 |
height |
number | Height above the target in m | -100 .. 1000 |
targetHeight |
number | Aim point above the target origin in m | -100 .. 100 |
lookAhead |
number | Seconds of velocity to aim ahead | 0 .. 5 |
stiffness |
number | Position spring in 1/s (higher = tighter) | 0.1 .. 100 |
turnStiffness |
number | How fast the arm swings behind the target in 1/s | 0.1 .. 100 |
fovMin |
number | Field of view at a standstill (degrees) | 5 .. 170 |
fovMax |
number | Field of view at fovSpeed (degrees) | 5 .. 170 |
fovSpeed |
number | Speed in m/s where the field of view reaches fovMax | 0.1 .. 1000 |
collide |
boolean | Pull the camera in when a wall blocks the view |
physics_world¶
Scene-wide physics settings. One per scene (on any entity; the physics_settings tool manages it).
| Field | Type | Description | Values |
|---|---|---|---|
gravity |
number[3] | Gravity in m/s^2 (Earth [0,-9.81,0], Moon [0,-1.62,0]) | |
substeps |
integer | Collision steps per tick (1..8; more = stabler stacks, fast objects) | |
ignorePairs |
string | Comma-separated layer pairs that never collide, e.g. "debris-player, projectile-projectile" (layers: default, static, player, enemy, projectile, trigger, debris) | |
allowSleep |
boolean | Let resting bodies sleep (much cheaper) | |
enabled |
boolean | Run the physics simulation while playing |
navmesh¶
Navigation-mesh bake settings and the saved bake (one per scene; nav_build creates it). Walkable surfaces come from static colliders and static meshes.
| Field | Type | Description | Values |
|---|---|---|---|
agentRadius |
number | Agent radius in m (walls are eroded by it) | 0 .. 20 |
agentHeight |
number | Agent height in m (lower ceilings block) | 0.1 .. 50 |
maxClimb |
number | Highest step in m | 0 .. 20 |
maxSlope |
number | Steepest walkable slope in degrees | 0 .. 89 |
cellSize |
number | Voxel size in m (radius/2..radius/3 is typical) | 0.01 .. 5 |
cellHeight |
number | Voxel height in m | 0.01 .. 5 |
tileSize |
integer | Cells per tile side (16..256) | |
geometry |
string | Input: both (colliders where present, else meshes), colliders only, or render meshes only | both colliders meshes |
data |
string | Baked navmesh file (project-relative), written by nav_build | |
autoBuild |
boolean | Bake when play starts if the saved bake is missing or stale |
nav_agent¶
Path-finding agent on the navigation mesh with local avoidance (crowds). Wander: navigate(self, target), stop_navigation(self), arrived(self); fires on event "arrived". With a character component it walks the controller; otherwise it moves the transform.
| Field | Type | Description | Values |
|---|---|---|---|
speed |
number | Max speed in m/s | 0 .. 100 |
acceleration |
number | Acceleration in m/s^2 | 0.01 .. 1000 |
radius |
number | Radius used for avoidance in m | 0.05 .. 20 |
height |
number | Height in m | 0.1 .. 50 |
stoppingDistance |
number | Arrival tolerance in m | 0 .. 100 |
turnSpeed |
number | Degrees/s to face the movement (0 = never rotate) | 0 .. 100000 |
destination |
number[3] | World point to walk to (with navigating = true) | |
navigating |
boolean | Heading to the destination (cleared on arrival) | |
autoRepath |
boolean | Re-plan when blocked or when the destination changes | |
avoidance |
string | Local avoidance quality | none low medium high |