@threenative/physics API
Every public function and class in @threenative/physics. Thin Rapier physics bindings for ThreeNative games.
On this page
Generated from the engine's capability manifest: 8 functions and 11 classes. Each entry is the exported signature, what it is for, and a working example. Start with the package overview.
Area3D
Detect overlaps without turning the body into a moving collider.
class Area3DDeprecated
- Constructor option
worldis deprecated; pass an IPhysicsContext asphysicsinstead. Area3D itself is not deprecated.
Use it to
- detect when an enemy enters a trigger area
- react to a player entering a zone
Example
const goal = new Area3D({ physics: ctx.physics, shape: CollisionShape3D.sphere(1.2), position: { x: 0, y: 0.5, z: -8 } });Good to know
- add the area to the physics context before stepping the world
Also found by
- pick up item
attachSnowPhysics
Drive a SnowField from real solved contacts. The binding creates the snow surface collider from the field's own canonical samples and keeps it in step with them, so a body lands on the surface a query would report. Each fixed step it reads the solver's persistent contacts — not collision start/stop events, which carry no point or load — deforms the snow only where a contact is supported and loaded downward, then republishes the surface before the next step. Airborne bodies, side contacts and unrelated colliders never deform anything. A dropped sphere settles on the surface it made; a pushed one rotates and carves a connected track without its transform being copied anywhere. Footprints come from the body's own collision shape and orientation unless the game supplies one. Contact load is impulse / deltaTime * loadScale: a solver impulse over a step, which estimates a contact force and is not measured. observe().loadProvenance says so.
function attachSnowPhysics(options: ISnowPhysicsOptions): ISnowPhysicsBindingNeeds
- @threenative/core/world SnowField as the surface it deforms
Use it to
- leave footprints and tracks where physical bodies actually touch snow
- let a dropped or pushed sphere carve and settle into deformable snow
- make a crate, capsule or ball compress the surface it rests on
Example
const snowPhysics = attachSnowPhysics({ physics: ctx.physics, snow, bodies: [ball] });
afterPhysics(ctx, (dt) => snowPhysics.step(dt));Good to know
- register
rapier()before attaching, and callsteponce per fixed step after the physics step - the backend must expose persistent solved contacts and in-place shape refresh; one that does not fails at attach
- verified on browser WebGPU and the native Linux desktop host; Android and iOS share the native seam but have not run it
- automatic profiles cover sphere, box and capsule; any other shape needs an explicit footprint
Options
- loadScale, supportNormal, colliderTolerance, deposition, wind, collisionLayer and collisionMask name the binding's own behaviour
boxFootprint
A rectangular contact: the face a box rests on, in the contact's own frame. Coverage is full across the face and fades just outside it; the bank rises beyond that.
function boxFootprint(halfWidth: number, halfDepth: number): ISnowFootprintUse it to
- let a crate, platform or plank press a rectangular pit into snow
- imprint a box's own footprint rather than a circle around it
Example
const footprint = boxFootprint(0.4, 0.25);Good to know
- halfWidth and halfDepth are metres; rotation comes from the contact, not the footprint
buildStaticColliders
Build fixed trimesh bodies from the meshes a game authored in a scene root.
function buildStaticColliders( context: IStaticColliderContext, root: Object3D, filter?: StaticColliderFilter, ): readonly RigidBody3D[]Use it to
- make the level I built stop the player
- turn a cathedral or map scene into static collision
Example
const colliders = buildStaticColliders(ctx, level, { predicate: (object) => object.name.startsWith("wall") });Good to know
- supply the game-owned predicate for decorative meshes; the helper throws when it selects nothing
- generated bodies use trimesh geometry and world-space instance transforms
Buoyancy3D
Float a rigid body on a game-owned height source with fixed-step force ordering.
class Buoyancy3DUse it to
- float a boat on waves
- keep a hull above a moving water surface
Example
new Buoyancy3D({ body, surface: field, hullPoints, density: 1_000, drag: 4 });Good to know
- supply hull points, density, drag, and the height source
Options
- buoyancy disables force application while submergedFraction remains measured
capsuleFootprint
A stadium contact: a rectangle of half-length halfHeight and half-width radius, capped by two half-discs of radius. The shape a capsule lies on, so a knocked-over body sinks along a line instead of at a point. Coverage is full across the body's own width and fades just outside it, so the body's edge never rests on a half-pressed rim; the bank rises beyond that.
function capsuleFootprint(halfHeight: number, radius: number): ISnowFootprintUse it to
- let a fallen capsule, limb or barrel leave a linear imprint in snow
- give a capsule a shape-appropriate snow contact instead of a sphere's dot
Example
const footprint = capsuleFootprint(0.5, 0.2);Good to know
- radius and halfHeight are metres and never grow with load
CharacterBody3D
Move a character body with collision-aware sliding.
class CharacterBody3DDeprecated
- Constructor option
worldis deprecated; pass an IPhysicsContext asphysicsinstead. CharacterBody3D itself is not deprecated.
Use it to
- move an enemy or player through a level
- keep a character from walking through walls
Example
const body = new CharacterBody3D({ object: hero, physics: ctx.physics, shape: CollisionShape3D.capsule(0.5, 0.35) });Good to know
- use moveAndSlide inside the physics update
Also found by
- raised platform gap hazard restart
- enemy targets cooldown reload win condition
- platformer double jump
- first person
- run jump coins goal
CollisionShape3D
Give a physics body a Three.js collision shape.
class CollisionShape3DUse it to
- add a capsule or box collider to a character
- configure the shape used by a rigid body
Example
const shape = CollisionShape3D.capsule(0.5, 0.35);Good to know
- create shapes through the owning physics context
Also found by
- passes through body
- arena walls pickups
interactionGroups
Encode collision layers and masks for Rapier groups.
function interactionGroups(layer: number, mask: number): numberUse it to
- make an enemy collide with the world but not pickups
- configure which physics layers interact
Example
const groups = interactionGroups(1, 3);Joint3D
Connect two physics bodies with a Godot-style joint.
class Joint3DDeprecated
- Constructor option
worldis deprecated; pass an IPhysicsContext asphysicsinstead. Joint3D itself is not deprecated.
Use it to
- constrain a rigid body to another body
- build a hinge or pin mechanism
- swing a pendulum, wrecking ball, or hinged door on a joint
Example
const hinge = Joint3D.hinge({ physics: ctx.physics, bodyA: beam, bodyB: bob, anchorA: { x: 0, y: 0, z: 0 }, anchorB: { x: 0, y: 2.4, z: 0 }, axis: { x: 1, y: 0, z: 0 } });Good to know
- both bodies must belong to the same physics context
PhysicsDirectSpaceState3D
Query the physics world without creating a body.
class PhysicsDirectSpaceState3DUse it to
- raycast for visibility or aiming
- find bodies inside a shape or point query
Example
const space = new PhysicsDirectSpaceState3D(context);Good to know
- query results are bounded by the configured result limit
Also found by
- hitscan camera
rapier
Install the Rapier physics plugin and simulation backend.
function rapier(options: IPhysicsOptions =Use it to
- add physics to a portable game
- provide the context used by character and rigid bodies
Example
const game = defineGame({ plugins: [rapier()] });Good to know
- place rapier() before recast() in the plugin list
RigidBody3D
Simulate a dynamic or static rigid body.
class RigidBody3DDeprecated
- Constructor option
worldis deprecated; pass an IPhysicsContext asphysicsinstead. RigidBody3D itself is not deprecated.
Use it to
- give a crate or prop physical motion
- create a body that collides with a character
- fire physical cannonballs that collide with ships or scenery
- fire a cannonball projectile with cannon smoke particles
- a bullet passes through a wall
Example
const crate = new RigidBody3D({ object, physics: ctx.physics, shape: CollisionShape3D.box(1, 1, 1), mass: 8 });Good to know
- register rapier() in the game plugin list before using bodies
Options
- continuousCollision: false opts one body out while body.continuousCollision still reports the effective setting
softBodyCollision
Feed existing rigid-body boxes into SoftBody3D without inventing a second collider API.
function softBodyCollision(...bodies: readonly RigidBody3D[]): ISoftBodyCollisionUse it to
- stop a cloth flag, cape, or curtain at an existing physics wall
- collide SoftBody3D with fixed box bodies
Example
const cloth = new SoftBody3D(mesh, { ...options, collision: softBodyCollision(wall) });Good to know
- every body must use CollisionShape3D.box and retain its Three.js object transform
- rotated boxes become conservative cloth-local axis-aligned bounds
VehicleBody3D
Drive a car on ray-cast suspension instead of faking speed and heading.
class VehicleBody3D extends RigidBody3DUse it to
- drive a car, truck or bike around a track
- make a vehicle roll over kerbs, brake into a corner or stop at a wall
Example
const car = new VehicleBody3D({ object: chassis, physics: ctx.physics, shape: CollisionShape3D.box(1.6, 0.5, 3.6), mass: 900, wheels: [{ position: { x: 0.8, y: -0.15, z: -1.2 }, wheelRadius: 0.34, suspensionRestLength: 0.3, suspensionStiffness: 100, dampingCompression: 2.3, dampingRelaxation: 4.4, wheelFrictionSlip: 10.5, maxSuspensionTravel: 0.3, useAsSteering: true, useAsTraction: false }] });Good to know
- write engineForce, brake and steering every physics update; a car with no input does not move
- suspensionStiffness is a frequency squared, not newtons per metre; 100 is a road car and 20 bottoms out
Options
- a wheel ray never hits the chassis it hangs from, and it honours the chassis collision mask
- continuousCollision is on for the chassis, so a fast car cannot tunnel through a wall
Also found by
- racing car racing kart drift vehicle go-kart
- suspension wheel traction tyre grip
- accelerator pedal handbrake steering wheel
- rescue respawn flip back on track
NavigationAgent3D
Move an agent along a baked navmesh toward a target.
class NavigationAgent3DUse it to
- enemy walks around a wall
- enemy patrols a level and chases the player
- enemy walks around a patrol path and chases the player when it sees them
- enemy patrols and chases while avoiding obstacles
- enemy chases the player with line of sight and obstacle avoidance
- NPC walks to a destination
- move crew around a ship deck
Example
import { NavigationAgent3D } from "@threenative/physics/navigation";
import { Vector3 } from "three";
const agent = new NavigationAgent3D({ navigation, object });
agent.setTargetPosition(player.position);
const reusableTarget = new Vector3();
const next = agent.getNextPathPosition(reusableTarget);Good to know
- import NavigationAgent3D from exactly
@threenative/physics/navigation;@threenative/physicsis not a valid import for this symbol; use this capability instead of hand-written A*; requires recast() after rapier(), plus a baked NavigationRegion3D
Also found by
- close engagement range
NavigationObstacle3D
Add a non-moving crowd obstacle to a navmesh.
class NavigationObstacle3DUse it to
- keep navigation agents away from a blocking prop
- make a stationary character affect crowd avoidance
Example
const obstacle = new NavigationObstacle3D({ navigation, object });Good to know
- create it after recast() and dispose it with the scene
NavigationRegion3D
Bake walkable Three.js geometry into a navigation region.
class NavigationRegion3DUse it to
- let enemies walk around level geometry
- create the baked navmesh required by NavigationAgent3D
Example
const region = new NavigationRegion3D({ navigation, meshes: [floor] });Good to know
- bake before creating agents or obstacles
recast
Install navmesh pathfinding and crowd avoidance.
function recast(): NavigationPluginUse it to
- enemy walks around a wall
- NPC patrols a level and chases a player
Example
const game = defineGame({ plugins: [rapier(), recast()] });Good to know
- requires rapier() earlier in the plugins array