Gessa Docs
Recipes

Recipe

Doors buttons levers and press-to-interact

The player walks up to a door and it opens, or presses a key near a lever and a gate lifts. There is no InteractableComponent, DamageOnContactComponent, or button component (all stripped patterns); interaction is authored as a trigger or an input action plus a script that mutates the target.
engine v1.0.234since script-semantic-patch-ops.v1, action-catalog.v1.0.232, physics.v1, mutation.v1, hierarchy.v1, audio.v1Copy for LLM

Use this for

a door that opens on approach or on a key press; buttons, levers, switches, and pressure plates; any "when the player interacts, something happens" object

Not for

teleport pads that move the player (see teleporters-and-portals); a platform that moves on its own with no input (see moving-platforms-and-elevators); collecting an item on touch (see collectibles-and-scoring)

Pairs with: Input mapping actions bindings keyboard mouse gamepad touch, Moving platforms, elevators, rotating hazards, and objects on a patrol path, Physics colliders rigid bodies triggers and joints, Audio sound effects music and positional feedback

The recipe

Author with project_apply_script_semantic_patch using the ai_safe op pack.

  1. Give the interactive object a trigger ColliderComponent (collision:"trigger") sized to the reach zone, via project_add_component. A solid collider blocks the player instead of detecting them.
  2. Auto path (open on approach): addTriggerHandler { "handlerKey":"onApproach" }. Inside the handler body (whole-body GessaScript via replaceScriptFromGessaScript) open the door: ctx.entity.patchComponent the door's TransformComponent to the open position or rotation, then ctx.audio.play a latch sound. Set setBooleanState { "field":"doorOpen", "value": true } so re-entry is idempotent.
  3. Press path (open on key): declare an interact action (see input-mapping-actions-bindings) and addActionHandler { "actionKey":"interact" }. In the body, confirm the player is in range before acting: ctx.physics.overlapTest a small shape at the player, or ctx.world.find the nearest door and compare positions, THEN patch it open.
  4. Show that an object is usable with a HighlightComponent (enabled:true, pick a color) toggled on while the player is inside the trigger.
  5. Hinged swing vs slide: to swing, parent the door mesh under a hinge entity with ctx.entity.setParent and patch the hinge rotation; to slide, patch the door position. If the mesh carries an open clip, drive an AnimationStateComponent (clipKey:"open", playMode:"once") instead.

Pitfalls

  • addActionHandler fires for the action everywhere, not only near the object. Always gate with an overlap or distance check, or the far door opens too.
  • Transform and component patches run on the server authority (hierarchy.server_authority); the door opens for every player, which is what you want for a shared door. Do not try to open it client-side.
  • A door whose mesh origin is centered rotates around its middle, not its edge. Parent it under a hinge pivot and rotate the parent.
  • Track open/closed with setBooleanState, not a local variable, so a reload or a second player sees the same door state.

Verify

  • simulation_run (qa.run.start) to prove approach and press both open the door and that a closed door blocks passage.
  • project_get_graph_snapshot to confirm the trigger collider and the trigger or action handler landed on the graph.
Was this helpful?Report an issueContact support

On this page