Interaction
Interaction is how the player acts on the world with a single key. Any object can show an interaction prompt and call your script when it is used. Feather also includes ready-made interactions that need no script: doors that swing open and can be locked with a key item, switches that open and close linked doors, item pickups, containers, and carrying and throwing physics objects.
All of them use the Interact action (E by default; West on a gamepad), and their state is kept in saves.
What’s included
Section titled “What’s included”- Interaction prompts on any object, with custom text, that call
on_interact(id). - Doors that swing about a hinge, optionally locked with an item that can be used up.
- Switches — levers or buttons — that toggle doors and other switches.
- Pickups that put an item in the inventory and remove the object.
- Containers the player opens to take and put items.
- Carrying and throwing dynamic bodies, with thrown objects dealing blunt damage to enemies.
Add an interaction prompt
Section titled “Add an interaction prompt”- Select the object.
- In Details → Tags & interaction, turn on Interactable (E).
- Enter the Prompt text, for example “Read” or “Talk”.
- Handle the interaction in a world script:
fn on_interact(id) { if id == "27" { print("The note reads: meet me at the lighthouse."); }}The prompt appears when the player is within the interaction distance, set in
Window → Game logic → Game settings → Interaction distance (0.5–20 m, default 2.5 m). Scripts can
change a prompt at runtime with set_interact(id, prompt).
- Select the door object and choose Details → Add Component → Door.
- Set how far it Swings, where the Hinge sits, and how long it Takes.
- To lock it, turn on Locked and choose the Key item. Turn on Uses up the key to take the key from the player when it unlocks.
- Give the door a Kinematic body so it pushes things as it moves.
| Field | Description | Range | Default |
|---|---|---|---|
open_degrees |
How far it swings; negative swings the other way | −180 to 180° | 95° |
hinge |
Hinge in the object’s local box; [-0.5, 0, 0] is the left edge |
±5 | [−0.5, 0, 0] |
seconds |
Time to open or close | 0.05–30 s | 0.7 s |
locked_with |
Item ID that unlocks it; null is never locked |
— | None |
consume_key |
Unlocking uses the key up | On/off | Off |
starts_open |
Open when Play starts | On/off | Off |
sound |
Sound cue or sound played when it moves | — | Empty |
Switches
Section titled “Switches”- Select the lever or button and choose Details → Add Component → Switch.
- Under Opens and closes, choose Add a door for each door or switch it drives.
- Set the Prompt, and whether it Starts on or works Only once.
| Field | Description | Range | Default |
|---|---|---|---|
targets |
Object IDs of the doors or switches it drives | Up to 32 | None |
prompt |
Prompt text | 1–80 characters | Pull |
once |
Can only be used once | On/off | Off |
starts_on |
On when Play starts | On/off | Off |
tilt |
Degrees the switch object tips when on; 0 keeps it still | −120 to 120° | 40° |
sound |
Sound played when used | — | Empty |
Pickups and containers
Section titled “Pickups and containers”A Pickup component puts its item in the inventory when the player interacts with it, and the object disappears. A Container opens a screen to take and put items. Both are covered in Items and inventory.
Carrying and throwing
Section titled “Carrying and throwing”The player looks at a dynamic body and presses Interact to pick it up, and presses it again to set it down. The Throw action (left mouse by default) hurls it. Heavier objects fly slower, and thrown objects deal blunt damage to enemies they hit.
Configure it in Window → World & terrain → Items → Carrying & throwing.
| Setting | Field | Range | Default |
|---|---|---|---|
| Pick up physics objects | carry |
On/off | On |
| Heaviest | carry_max_mass |
0–10,000 kg | 60 kg |
| Held at | hold_distance |
0.5–6 m in front of the camera | 1.8 m |
| Throw speed | throw_speed |
0–60 m/s for a light object | 13 m/s |
| Throw damage | throw_damage |
0–10 blunt damage per kg·m/s | 0.12 |
| Throw action | throw_action |
An input action ID | throw |
Door, lever, pickup, chest and throw sounds can be replaced with your own cues in Built-in sounds under the player’s game feel settings; see Player and traversal.
Extend it
Section titled “Extend it”| Function | Description |
|---|---|
use_object(id) |
Acts as if the player pressed Interact on the object: opens doors, pulls switches, takes pickups |
door_open(id) |
Whether a door is open |
carry_object(id) |
Picks up a dynamic body, including one that has settled at rest |
throw_carried(), drop_carried() |
Throws or sets down what the player carries |
carrying() |
The ID of the carried object, or () |
use_tool() |
Casts the worn tool where the camera aims |
set_interact(id, prompt) |
Changes an object’s prompt |
tune("interaction", patch) |
Changes the carrying and throwing settings at runtime, for example a heavier carry_max_mass after an upgrade |
on_interact(id) still runs when the player uses a door, switch or pickup, so you can add
behaviour on top of the built-in one.
// A world script: react when the player pulls lever 40 and gate 41 opens.fn on_interact(id) { if id == "40" && door_open(41) { print("The gate is open. Guards are coming."); }}Limits
Section titled “Limits”- A switch drives at most 32 targets.
- A door’s hinge must be within ±5 of the object’s local box.
- Only dynamic bodies up to
carry_max_masscan be carried.
Automate it
Section titled “Automate it”# Lock door 41 with the "key" item, used up on unlockfeather-cli --connect .feather-session.json command scene.update \ --json '{"id":41,"patch":{"door":{"open_degrees":-100,"locked_with":"key","consume_key":true}}}'
# A lever (object 40) that opens door 41feather-cli --connect .feather-session.json command scene.update \ --json '{"id":40,"patch":{"switch":{"targets":[41],"prompt":"Pull lever"}}}'
# Let the player lift heavier objectsfeather-cli --connect .feather-session.json command interaction.set \ --json '{"patch":{"carry_max_mass":120,"throw_speed":16}}'interaction.get lists the carrying settings and the level’s doors, switches and pickups.