Skip to content

PhysicsSyncSystem

Initializes and manages the Rapier physics world, creates rigid bodies and colliders from PhysicsComponent authoring state, steps the simulation each frame, and writes the results back to entity transforms.

Overview

PhysicsSyncSystem runs every frame and is responsible for:

  • Lazy-initializing the Rapier physics engine (loaded asynchronously via @dimforge/rapier3d-compat) the first time the system updates.
  • Creating a Rapier RigidBody and Collider for each entity that has a PhysicsComponent and Object3DRef.
  • Recreating bodies and colliders when their type, shape, or size changes (detected by per-entity signatures).
  • Stepping the Rapier world each frame with the clamped delta time.
  • Writing the simulation's output (body translation + rotation) back into the entity's TransformComponent and THREE.js Object3D for dynamic and kinematic bodies.
  • Applying per-axis translation/rotation locks from PhysicsComponent.values.rigidbody.
  • Handling isSensor colliders that fire collision events without generating a physical response.

Queried components

ComponentAccess
PhysicsComponentRead + mutate (rigidBody, collider live refs; values for authoring state)
Object3DRefRead (initial world position for body placement)
TransformComponentMutate (position, rotation written from simulation output)
EnvironmentRead (global gravity vector)

Supported rigid body types

TypeDescription
dynamicFully simulated; affected by gravity and forces.
fixedImmovable; acts as a static collider.
kinematicPositionMoved by setting position directly; not affected by physics.
kinematicVelocityMoved by setting velocity; interacts with dynamics.

Supported collider shapes

ShapeParameters
cuboidwidth, height, depth
ballradius
capsuleradius, height
cylinderradius, height
trimeshAuto-extracted from the entity's THREE.js geometry

Behavior notes

  • Async init — the Rapier WASM module is loaded once on the first update() call. Physics simulation does not start until the module is ready; entities created before init are processed on the first frame after init completes.
  • Trimeshtrimesh colliders extract vertex/index data from the entity's THREE.BufferGeometry. The extracted data is cached per entity by a geometry signature.
  • Sensor colliders — setting values.collider.isSensor = true creates a Rapier sensor collider. Sensor contacts do not generate forces but can be used for overlap/trigger queries.
  • Gravity — the global gravity vector is read from the Environment component (gravity field, default { x: 0, y: -9.81, z: 0 }) and applied to the Rapier world gravity setting each frame.
  • Preview only — the system is typically constructed with { isEditor: false } for preview. In the editor the physics world step is skipped so objects don't fall during authoring.

API reference