Gessa Docs
Recipes

Recipe

Physics colliders rigid bodies triggers and joints

Anything that blocks movement, detects overlaps, falls under gravity, or is physically constrained to another body. Colliders are passive shapes; rigid bodies are dynamic; joints are constraints.
engine v1.0.234since component-field-contract ecs.component-field-contract.v1, physics.v1Copy for LLM

Use this for

making things solid, bouncy, or dynamic; trigger volumes; dynamic Rapier bodies; hinges, springs, and ropes between bodies

Not for

character walking motion (use CharacterMovementComponent); applying forces from author-time (use ctx.physics.command from a script)

Pairs with: World build document authoring compile apply loop, Third-person follow camera and platformer jump movement, Combat damage health and respawn scripting, Collectibles pickups scoring and win condition

Bodies first, components second

Place the physical entities themselves in bulk with the world build document (see authoring-with-the-world-build-document): the floor, the walls, the props. That lands their Transform and Renderable as one transaction. Physics is a COMPONENT layer attached on top: the document does not emit colliders or rigid bodies, so attach them as a precision step. To make many entities solid or dynamic at once, attach the components in ONE atomic project_apply_transaction rather than one entity per call.

The recipe

  1. Solid blocker or ground: attach ColliderComponent { "type":"ColliderComponent", "shape":"box", "collision":"solid", "size":{"x":10,"y":1,"z":10}, "layers":["default"], "friction":0.5, "restitution":0 }. shape is box, sphere, capsule, disc, or mesh.
  2. Trigger volume (fires overlap events, does not block): same component with "collision":"trigger". A script reacts with addTriggerHandler (its payload is {firstEntityId, secondEntityId, worldId, distance}). TRIGGER PARTICIPANT RULE (load-bearing, proven on the arena benchmark): the moving entity that should FIRE a static trigger must NOT carry a RigidBodyComponent. Any RigidBody hands that entity's pairs to Rapier, where a kinematic-vs-static-sensor pair is never reported, so the trigger silently never fires (16 entities in, 16 out, zero diagnostics). A player is CharacterMovementComponent with enableKcc plus a collider - no RigidBody, ever. If a trigger seems dead, check the toucher for a stray RigidBodyComponent first and remove it with project_remove_component.
  3. Dynamic object: add RigidBodyComponent { "type":"RigidBodyComponent", "bodyType":"dynamic", "mass":1, "gravityScale":1, "linearDamping":0, "angularDamping":0, "lockTranslations":{"x":false,"y":false,"z":false}, "lockRotations":{"x":false,"y":false,"z":false} }. bodyType is dynamic, kinematic, or static. Enable ccdEnabled for fast movers.
  4. Constrain two bodies: add JointComponent on the child body with jointType fixed, revolute, prismatic, spherical, spring, or rope, and set connectedEntityId to the other body. Anchors and axis are in each body's LOCAL space; motor and limits apply to revolute and prismatic joints.
  5. Apply an impulse or launch from a script (not from authoring): call ctx.physics.command(entityId, bodyCommand); query space with ctx.physics.overlapTest, ctx.physics.shapecast, ctx.physics.occupancyQuery.

Pitfalls

  • friction and restitution are clamped 0..1. A bouncy ball is high restitution; ice is low friction.
  • Do NOT author ForceComponent or VelocityComponent values: both are hidden internal runtime lanes. Forces go through ctx.physics.command; the movement vector is runtime-owned.
  • A RigidBodyComponent makes the runtime own that entity's Transform each tick. Do not also drive it with CharacterMovementComponent; pick one motor.
  • A collider with collision:"none" neither blocks nor triggers; it is only a query/placement shape.
  • Joint motor/limits on a fixed joint do nothing; they exist only on revolute and prismatic.
  • The document places the bodies; the per mutation call is the precision tier for attaching these components, not a bulk placement tool.

Verify

  • engine_get_component_schema on ColliderComponent and RigidBodyComponent for shape/bodyType enums.
  • simulation_run (qa.run.start) to confirm solids block and triggers fire.
  • runtime_proof_run (runtime.proof.run) for a deterministic physics transition receipt.
Was this helpful?Report an issueContact support

On this page