Use this guide as the default design standard for Perro gameplay scripts. It explains ownership and communication choices before listing macros. The goal is code whose data source, target, lifetime, and failure behavior are visible.
One script instance belongs to one node. ctx.id identifies that owner.
#[State] holds values that survive callbacks. A scene wires known dependencies
and per-instance assets through script_vars before on_init. Runtime calls
cross an ownership boundary only when the target owns the behavior or data.
scene construction -> script_vars -> on_init -> on_all_init -> update callbacks
owned node <-> owned typed state -> fixed refs / relations / queries -> other owners
| Need | Use |
|---|---|
| choose state fields, node refs, or asset IDs | State And References |
| edit self, another node, or another script | Node And State Access |
| choose typed state, methods, signals, or dynamic vars | Script Communication |
| use timers and avoid nested runtime borrows | Timers And Borrows |
| choose a callback and understand init order | Lifecycle |
| wire scenes and assign ownership | Ownership And Scene Wiring |
| choose fixed refs, relations, or queries | References And Queries |
| inject typed assets and understand lifetime | Typed Assets |
| spawn nodes or attach scripts at runtime | Spawn And Runtime Attach |
| split scripts, debug, test, and check perf | Boundaries And Quality |
| see several scripts form one feature | Examples |
| write or review docs examples | Documentation Standard |
- use
ctx.idfor the node that owns the current script - store fixed dependencies as scene-injected
NodeIDfields - use parent/child relations for structural dependencies
- use queries for dynamic sets, not fixed refs
- use
with_state!/with_state_mut!when the Rust state type is known - use
call_method!for a targeted dynamic command with params or a return value - use signals for events, fan-out, and loose or cross-scene flow
- use
get_var!/set_var!only when the member name or type is dynamic - declare dynamically dispatched members
pub:call_method!and signal handlers need apub fn,get_var!/set_var!apubstate field - use named timers for delays and cooldown completion
- copy values out of runtime closures before the next
ctx.runcall - split scripts by behavior ownership, not a fixed size rule
known Rust state type? -> with_state! / with_state_mut!
targeted behavior? -> call_method!
event or many listeners? -> signal_emit!
runtime member name? -> get_var! / set_var!
- Player, Camera, And HUD
- Switch Calls Door
- Manager And Spawned Enemies
- Pickup, Inventory, And UI
- Scene-Injected Asset Variants
- Timer-Driven Cooldown
- Dynamic Inspector Adapter
The runnable ScriptPatterns demo combines fixed refs, typed asset injection, methods, signal fan-out, dynamic vars, a named timer, typed node access, and borrow-safe flow.