Skip to content

Physics tools

Rigid bodies, characters, queries, settling and navigation meshes.

16 tools in the physics category. Badges: read-only tools never change the project; mutating tools are undoable and attributed; open-world tools reach outside the engine and MCP clients ask before running them.

Tool Summary
physics_add Make entities physical with a preset (one undoable edit).
physics_query Ask the collision world (colliders, not render meshes) — works while editing and playing.
physics_settle Drop objects with a real simulation and keep where they come to rest (simulate, then keep the poses).
physics_debug Capture the viewport with every collider drawn as a wireframe (color = state) plus physics stats (bodies, awake/asleep, contacts, triggers, characters, joints) and warnings (bad layers, unsupported shapes, missing joint targets).
physics_settings Read or change scene-wide physics: gravity (m/s^2), substeps (stability for stacks/fast objects), which collision layers ignore each other (ignorePairs, e.g.
nav_build Bake (or rebuild) the navigation mesh from static colliders and static meshes, save it to the project and record the settings in the scene's navmesh component (one undoable edit; creates an entity named "Navigation" if needed).
nav_path Walking path on the navmesh between two points or entities (bakes the navmesh first if needed).
nav_debug Top-down map of the level with the navmesh drawn over it (teal = walkable), nav agents (yellow dots) with their current paths, and optionally a test path between two points (orange).
vehicle_create Make a drivable car, truck or kart from a chassis entity whose wheel meshes are child entities named wheel* (wheel_fl, wheel_fr, wheel_rl, wheel_rr; or pass wheels).
vehicle_tune Change a vehicle's handling parameters with validation (one undoable edit; works while playing: the vehicle is rebuilt keeping its speed).
vehicle_info Live state of vehicles: speed (km/h), rpm, gear, inputs as asked and as applied after assists (steering smoothing, auto reverse, traction control, ABS, drift assist), drift angle, lateral/longitudinal g, and per wheel: suspension length/compression, contact point and surface, load (N), drive and cornering forces, slip ratio and slip angle, skid 0..1.
vehicle_test_drive An autopilot drives a copy of the vehicle through standard maneuvers in a private physics world (the scene is not changed; works while editing) and returns handling metrics to tune by numbers: accel (0-60, 0-100 km/h, quarter mile, wheelspin, upshifts), braking (distance and g from speed, default 100 km/h; ABS activity, stability), slalom (8 cones every cone_spacing m at speed, default 60: completed, cones hit, average speed, line error), skidpad (circle of radius m, speed ramps until the car leaves the line: max lateral g, and whether it understeers, oversteers or runs out of power), top_speed (duration s), custom (inputs keyframes [{t, throttle, brake, steer, handbrake}]), all (accel, braking, slalom, skidpad).
physics2d_info The 2D physics world (Box2D) at a glance: settings (gravity, sub-steps, debug draw), counts (bodies by motion, awake/sleeping, shapes, sensors, chains, characters, joints, contacts), each body and character2d with its velocity, sleeping/grounded state, tilemap collision pieces (merged loops/boxes/polygons), and warnings (bad polygons, unknown layers, missing joint bodies).
physics2d_add Make 2D entities physical with a preset (one undoable edit); colliders are fitted to the sprite.
physics2d_settle Drop 2D objects with a real simulation and keep where they come to rest: only the listed entities move (as dynamic bodies, even without body2d), everything else is frozen; the result is ONE undoable edit.
physics2d_query Ask the 2D collision world (collider2d shapes, character2d capsules) on the XY plane — works while editing and playing.

physics_add

Make physical mutating

Make entities physical with a preset (one undoable edit). prop = dynamic rigid body with a collider fitted to its mesh and a mass estimated from its size; static_level = static colliders for every mesh under the entity (triangle-exact for imported models) — use on level roots; kinematic_platform = moved by its transform/scripts, carries and pushes things; player_character / npc_character = capsule character controller fitted to the mesh (drive with walk/jump in Wander); trigger_zone = sensor that fires on trigger_enter/on trigger_exit; debris = light, does not collide with characters; projectile = fast (continuous collision); remove = strip body/collider/character/joint. overrides patches the components, e.g. {"body": {"mass": 80, "restitution": 0.6}, "collider": {"shape": "sphere"}}. Example: {"entities": ["Crate 1", "Crate 2"], "preset": "prop"}.

Argument Type Required Description Values
entity integer | string Entity (or use entities)
entities integer | string[] Entities to change
preset string yes What the entities become prop static_level kinematic_platform player_character npc_character trigger_zone debris projectile remove
overrides object Component patches, e.g. {"body": {...}, "collider": {...}, "character": {...}}
physics_add {"entities": ["Crate 1", "Crate 2"], "preset": "prop"}
skywalker call physics_add '{"entities": ["Crate 1", "Crate 2"], "preset": "prop"}' --project my_game
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "physics_add",
    "arguments": {
      "entities": [
        "Crate 1",
        "Crate 2"
      ],
      "preset": "prop"
    }
  }
}

physics_query

Physics query read-only

Ask the collision world (colliders, not render meshes) — works while editing and playing. raycast = first hit along a ray; raycast_all = every entity along it; shapecast = sweep a sphere/box/capsule (will this fit / where does it land?); overlap = entities touching a shape at origin (is this spot free?). Triggers are ignored unless include_triggers. Example: {"type": "raycast", "origin": [0, 10, 0], "direction": [0, -1, 0]}.

Argument Type Required Description Values
type string yes Query kind raycast raycast_all shapecast overlap
origin number[3] yes Ray/sweep start, or the overlap shape center
direction number[3] Ray/sweep direction (default [0,-1,0])
max_distance number Max distance in m (default 100)
shape string shapecast/overlap shape (default sphere) sphere box capsule
radius number Sphere/capsule radius (default 0.5)
height number Capsule total height (default 1.8)
half_extents number[3] Box half size (default [0.5,0.5,0.5])
rotation number[3] Shape rotation, Euler degrees
exclude integer | string[] Entities to ignore
include_triggers boolean Also report trigger zones
layers string[] Only these collision layers
physics_query {"type": "raycast", "origin": [0, 10, 0], "direction": [0, -1, 0]}
skywalker call physics_query '{"type": "raycast", "origin": [0, 10, 0], "direction": [0, -1, 0]}' --project my_game
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "physics_query",
    "arguments": {
      "type": "raycast",
      "origin": [
        0,
        10,
        0
      ],
      "direction": [
        0,
        -1,
        0
      ]
    }
  }
}

physics_settle

Settle with physics mutating

Drop objects with a real simulation and keep where they come to rest (simulate, then keep the poses). Only the listed entities move (as dynamic bodies, even without a body component); everything else is frozen. The result is ONE undoable edit. Great after scatter/place: rocks, crates, books and debris end up naturally stacked and resting instead of floating or intersecting. Example: {"entities": ["Crate 1", "Crate 2", "Barrel"], "seconds": 4}.

Argument Type Required Description Values
entity integer | string Entity to settle (or use entities)
entities integer | string[] Entities to settle (top-level props)
seconds number Max simulated seconds (default 4, max 30); stops early when everything sleeps
freeze_others boolean Keep other dynamic bodies still (default true)
physics_settle {"entities": ["Crate 1", "Crate 2", "Barrel"], "seconds": 4}
skywalker call physics_settle '{"entities": ["Crate 1", "Crate 2", "Barrel"], "seconds": 4}' --project my_game
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "physics_settle",
    "arguments": {
      "entities": [
        "Crate 1",
        "Crate 2",
        "Barrel"
      ],
      "seconds": 4
    }
  }
}

physics_debug

See colliders read-only

Capture the viewport with every collider drawn as a wireframe (color = state) plus physics stats (bodies, awake/asleep, contacts, triggers, characters, joints) and warnings (bad layers, unsupported shapes, missing joint targets). Use it to check that colliders match the visuals, triggers sit where you expect, and props fall asleep. view: editor (default), scene camera, or top (orthographic map).

Argument Type Required Description Values
view string Camera editor scene top
focus integer | string Frame this entity
width integer Image width (default 768)
height integer Image height (default 432)
show_static boolean Draw static colliders (default true)
include_image boolean Return the image (default true)
physics_debug {"view": "top"}
skywalker call physics_debug '{"view": "top"}' --project my_game
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "physics_debug",
    "arguments": {
      "view": "top"
    }
  }
}

physics_settings

Physics settings mutating

Read or change scene-wide physics: gravity (m/s^2), substeps (stability for stacks/fast objects), which collision layers ignore each other (ignorePairs, e.g. "debris-player, projectile-projectile"), sleeping, on/off. Stored in a physics_world component (created on an entity named "Physics" when you first change it). Example: {"gravity": [0, -1.62, 0]} for the Moon.

Argument Type Required Description Values
gravity number[3] Gravity vector in m/s^2
substeps integer Collision steps per tick (1..8)
ignorePairs string Layer pairs that never collide, comma separated
allowSleep boolean Let resting bodies sleep
enabled boolean Simulate physics while playing
physics_settings {"gravity": [0, -1.62, 0]}
skywalker call physics_settings '{"gravity": [0, -1.62, 0]}' --project my_game
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "physics_settings",
    "arguments": {
      "gravity": [
        0,
        -1.62,
        0
      ]
    }
  }
}

Bake navmesh mutating

Bake (or rebuild) the navigation mesh from static colliders and static meshes, save it to the project and record the settings in the scene's navmesh component (one undoable edit; creates an entity named "Navigation" if needed). Re-run after changing the level layout. Settings default to the navmesh component's: agent_radius (walls eroded by it), agent_height, max_climb (steps), max_slope (degrees), cell_size (precision). Entities tagged "nav_ignore" are left out. Then use nav_path / nav_debug, or nav agents and navigate() in Wander.

Argument Type Required Description Values
agent_radius number Agent radius in m (default 0.4)
agent_height number Agent height in m (default 1.8)
max_climb number Highest step in m (default 0.4)
max_slope number Steepest walkable slope in degrees (default 45)
cell_size number Voxel size in m (default 0.2; smaller = more precise, slower)
cell_height number Voxel height in m (default 0.1)
tile_size integer Cells per tile (default 64)
geometry string Input geometry (default both) both colliders meshes
save boolean Write the navmesh file (default true)
path string Project-relative file (default: next to the scene, <scene>.navmesh)
nav_build {"agent_radius": 0.4, "agent_height": 1.8, "max_climb": 0.4, "max_slope": 45, "cell_size": 0.2}
skywalker call nav_build '{"agent_radius": 0.4, "agent_height": 1.8, "max_climb": 0.4, "max_slope": 45, "cell_size": 0.2}' --project my_game
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "nav_build",
    "arguments": {
      "agent_radius": 0.4,
      "agent_height": 1.8,
      "max_climb": 0.4,
      "max_slope": 45,
      "cell_size": 0.2
    }
  }
}

Find path read-only

Walking path on the navmesh between two points or entities (bakes the navmesh first if needed). Returns the corner points, the walking length, and whether the goal is reachable (partial = it is not; the path ends at the closest reachable point). Use to check that a level is traversable or to plan patrols. Example: {"from": "Player", "to": [12, 0, -4]}.

Argument Type Required Description Values
from any yes Start: [x, y, z] or an entity
to any yes Goal: [x, y, z] or an entity
nav_path {"from": "Player", "to": [12, 0, -4]}
skywalker call nav_path '{"from": "Player", "to": [12, 0, -4]}' --project my_game
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "nav_path",
    "arguments": {
      "from": "Player",
      "to": [
        12,
        0,
        -4
      ]
    }
  }
}

See navmesh read-only

Top-down map of the level with the navmesh drawn over it (teal = walkable), nav agents (yellow dots) with their current paths, and optionally a test path between two points (orange). The fastest way to spot unreachable rooms, doorways too narrow for agents, and gaps. Bakes the navmesh first if needed.

Argument Type Required Description Values
focus integer | string Frame this entity instead of the whole navmesh
from any Optional test path start: [x, y, z] or an entity
to any Optional test path goal
size integer Image size in pixels (default 640)
include_image boolean Return the image (default true)
nav_debug {"from": "Player", "to": [12, 0, -4], "size": 800}
skywalker call nav_debug '{"from": "Player", "to": [12, 0, -4], "size": 800}' --project my_game
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "nav_debug",
    "arguments": {
      "from": "Player",
      "to": [
        12,
        0,
        -4
      ],
      "size": 800
    }
  }
}

vehicle_create

Create vehicle mutating

Make a drivable car, truck or kart from a chassis entity whose wheel meshes are child entities named wheel* (wheel_fl, wheel_fr, wheel_rl, wheel_rr; or pass wheels). One undoable edit that adds: a dynamic body (chassis mass), a box collider fitted to the chassis above the wheels, the vehicle component from a preset (sports, hatchback, truck, kart) in a handling style (arcade = traction control, ABS, drift assist, roll protection; sim = raw), a chase camera on the scene camera, a looping engine sound pitched by rpm, and the drive input actions (throttle W/Up/right trigger, brake+reverse S/Down/left trigger, steer A-D/arrows/left stick, handbrake Space/A). Forward is -Z. Wheels are fitted from their meshes and spin, steer and follow the suspension while playing. Then: vehicle_test_drive for numbers, vehicle_tune to adjust, vehicle_info capture=true to see suspension and tire forces. Example: {"entity": "Coupe", "preset": "sports"}.

Argument Type Required Description Values
entity integer | string yes The chassis (root of the car model)
preset string Vehicle type (default sports) sports hatchback truck kart
handling string arcade (assists, default) or sim arcade sim
wheels integer | string[] Wheel entities (children of the chassis); default: children named wheel*
overrides object vehicle component fields to set on top of the preset
chase_camera boolean Make the scene camera a chase camera following this vehicle (default true)
engine_sound boolean Add a looping engine sound pitched by rpm (default true)
input_actions boolean Add the drive input actions to the project's input map if missing (default true)
collider string auto = box fitted to the chassis above the wheels (default); keep = your own auto keep
vehicle_create {"entity": "Coupe", "preset": "sports"}
skywalker call vehicle_create '{"entity": "Coupe", "preset": "sports"}' --project my_game
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "vehicle_create",
    "arguments": {
      "entity": "Coupe",
      "preset": "sports"
    }
  }
}

vehicle_tune

Tune vehicle mutating

Change a vehicle's handling parameters with validation (one undoable edit; works while playing: the vehicle is rebuilt keeping its speed). set takes vehicle component fields, e.g. {"maxTorque": 600, "lateralGrip": 1.6, "antiRollRear": 12000, "driftAssist": 0.5}; unknown fields fail with a did-you-mean. preset + handling re-apply a preset first. wheels overrides per axle or wheel ({"rear": {"lateralGrip": 1.2}, "front_left": {...}}): the wheel list is written out from the current fit the first time. test (a maneuver: accel, braking, slalom, skidpad, all) drives before and after the change and returns both summaries, so you can tune by numbers. Run vehicle_test_drive for details.

Argument Type Required Description Values
entity integer | string yes The vehicle
set object vehicle fields to change
preset string Re-apply a preset (before set) sports hatchback truck kart
handling string Handling style for preset (default arcade) arcade sim
wheels object Per-wheel overrides keyed by axle (front, rear) or wheel name (front_left, rear_right, axle1_left):
test string Measure this maneuver before and after the change accel braking slalom skidpad top_speed all
vehicle_tune {"entity": "Coupe", "set": {"maxTorque": 600, "lateralGrip": 1.2}, "test": "accel"}
skywalker call vehicle_tune '{"entity": "Coupe", "set": {"maxTorque": 600, "lateralGrip": 1.2}, "test": "accel"}' --project my_game
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "vehicle_tune",
    "arguments": {
      "entity": "Coupe",
      "set": {
        "maxTorque": 600,
        "lateralGrip": 1.2
      },
      "test": "accel"
    }
  }
}

vehicle_info

Vehicle telemetry read-only

Live state of vehicles: speed (km/h), rpm, gear, inputs as asked and as applied after assists (steering smoothing, auto reverse, traction control, ABS, drift assist), drift angle, lateral/longitudinal g, and per wheel: suspension length/compression, contact point and surface, load (N), drive and cornering forces, slip ratio and slip angle, skid 0..1. While editing it shows the fitted setup at rest (wheel roles, radii) and build warnings. capture=true adds an image with the vehicles debug view (suspension rays, contacts, tire force vectors). Without entity it lists every vehicle. Pair with sim_control step / sim_input to watch a maneuver.

Argument Type Required Description Values
entity integer | string A vehicle (default: all)
wheels boolean Include per-wheel data (default true)
capture boolean Add a picture with the vehicles debug view (default false)
width integer Capture width (default 960)
height integer Capture height (default 540)
vehicle_info {"entity": "Coupe", "capture": true}
skywalker call vehicle_info '{"entity": "Coupe", "capture": true}' --project my_game
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "vehicle_info",
    "arguments": {
      "entity": "Coupe",
      "capture": true
    }
  }
}

vehicle_test_drive

Test drive read-only

An autopilot drives a copy of the vehicle through standard maneuvers in a private physics world (the scene is not changed; works while editing) and returns handling metrics to tune by numbers: accel (0-60, 0-100 km/h, quarter mile, wheelspin, upshifts), braking (distance and g from speed, default 100 km/h; ABS activity, stability), slalom (8 cones every cone_spacing m at speed, default 60: completed, cones hit, average speed, line error), skidpad (circle of radius m, speed ramps until the car leaves the line: max lateral g, and whether it understeers, oversteers or runs out of power), top_speed (duration s), custom (inputs keyframes [{t, throttle, brake, steer, handbrake}]), all (accel, braking, slalom, skidpad). track=proving_ground (default: flat, full grip, comparable between cars) or scene (the level as it is). overrides tries vehicle fields without editing (e.g. {"lateralGrip": 1.6}). trace=true adds a sampled trace. Example: {"entity": "Coupe", "maneuver": "all"}.

Argument Type Required Description Values
entity integer | string yes The vehicle
maneuver string What to drive (default all) accel braking slalom skidpad top_speed custom all
speed number km/h: braking start (100), slalom (60), skidpad start (30)
duration number Seconds for top_speed (45) / custom
radius number Skidpad radius in m (default 40)
cone_spacing number Slalom cone spacing in m (default 18)
inputs object[] custom: keyframes
overrides object vehicle fields for this drive only
track string Where to drive (default proving_ground) proving_ground scene
trace boolean Include a trace sampled every 0.25 s
vehicle_test_drive {"entity": "Coupe", "maneuver": "all"}
skywalker call vehicle_test_drive '{"entity": "Coupe", "maneuver": "all"}' --project my_game
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "vehicle_test_drive",
    "arguments": {
      "entity": "Coupe",
      "maneuver": "all"
    }
  }
}

physics2d_info

2D physics info read-only

The 2D physics world (Box2D) at a glance: settings (gravity, sub-steps, debug draw), counts (bodies by motion, awake/sleeping, shapes, sensors, chains, characters, joints, contacts), each body and character2d with its velocity, sleeping/grounded state, tilemap collision pieces (merged loops/boxes/polygons), and warnings (bad polygons, unknown layers, missing joint bodies). Works while editing (an edit-time mirror) and playing. Pass entity for one entity only. Example: {"entity": "Player"}.

Argument Type Required Description Values
entity integer | string Only this entity
limit integer Max bodies listed (default 50)
physics2d_info {"entity": "Player"}
skywalker call physics2d_info '{"entity": "Player"}' --project my_game
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "physics2d_info",
    "arguments": {
      "entity": "Player"
    }
  }
}

physics2d_add

Make 2D physical mutating

Make 2D entities physical with a preset (one undoable edit); colliders are fitted to the sprite. platformer_player = character2d controller (drive with move2d/jump2d in Wander); crate = dynamic box; ball = bouncy dynamic circle; one_way_platform = static box you can jump through from below; tilemap_collision = merged collision from the entity's tilemap (solid layers, per-tile slopes and one-way tiles); static_ground = static box; sensor_zone = trigger area (on trigger_enter / on trigger_exit); moving_platform = kinematic box (move it with its transform or body2d.velocity); remove = strip the 2D physics components. overrides patches the components: {"collider2d": {"restitution": 0.9}, "character2d": {"jumpSpeed": 14}}. Example: {"entity": "Player", "preset": "platformer_player"}.

Argument Type Required Description Values
entity integer | string Entity (or use entities)
entities integer | string[] Entities to change
preset string yes What the entities become platformer_player crate ball one_way_platform tilemap_collision static_ground sensor_zone moving_platform remove
overrides object Component patches: {"body2d": {...}, "collider2d": {...}, "character2d": {...}}
physics2d_add {"entity": "Player", "preset": "platformer_player"}
skywalker call physics2d_add '{"entity": "Player", "preset": "platformer_player"}' --project my_game
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "physics2d_add",
    "arguments": {
      "entity": "Player",
      "preset": "platformer_player"
    }
  }
}

physics2d_settle

Settle with 2D physics mutating

Drop 2D objects with a real simulation and keep where they come to rest: only the listed entities move (as dynamic bodies, even without body2d), everything else is frozen; the result is ONE undoable edit. Use after placing crates, rocks or props on a level so they rest on the ground and on each other. Example: {"entities": ["Crate 1", "Crate 2"], "seconds": 3}.

Argument Type Required Description Values
entity integer | string Entity to settle (or use entities)
entities integer | string[] Entities to settle
seconds number Max simulated seconds (default 4, max 30); stops early when everything sleeps
freeze_others boolean Keep other dynamic bodies still (default true)
physics2d_settle {"entities": ["Crate 1", "Crate 2"], "seconds": 3}
skywalker call physics2d_settle '{"entities": ["Crate 1", "Crate 2"], "seconds": 3}' --project my_game
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "physics2d_settle",
    "arguments": {
      "entities": [
        "Crate 1",
        "Crate 2"
      ],
      "seconds": 3
    }
  }
}

physics2d_query

2D physics query read-only

Ask the 2D collision world (collider2d shapes, character2d capsules) on the XY plane — works while editing and playing. raycast = first hit along a ray; raycast_all = every entity along it; overlap_circle / overlap_box = entities touching the shape at origin (is this spot free?); point = entities containing the point. Sensors are ignored unless include_sensors. Example: {"type": "raycast", "origin": [2, 5], "direction": [0, -1]}.

Argument Type Required Description Values
type string yes Query kind raycast raycast_all overlap_circle overlap_box point
origin number[] yes Ray start, shape center or point [x, y]
direction number[] Ray direction [x, y] (default [0, -1])
max_distance number Max ray distance (default 100)
radius number overlap_circle radius (default 0.5)
half_extents number[] overlap_box half size [x, y] (default [0.5, 0.5])
angle number overlap_box rotation in degrees
exclude integer | string[] Entities to ignore
include_sensors boolean Also report sensors
layers string[] Only these collision layers
physics2d_query {"type": "raycast", "origin": [2, 5], "direction": [0, -1]}
skywalker call physics2d_query '{"type": "raycast", "origin": [2, 5], "direction": [0, -1]}' --project my_game
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "physics2d_query",
    "arguments": {
      "type": "raycast",
      "origin": [
        2,
        5
      ],
      "direction": [
        0,
        -1
      ]
    }
  }
}