You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The scripts module is how one script reaches another. It reads and writes the
typed state a script owns, calls its methods by name, and manages script
lifetime at runtime (attach, detach, enable/disable per-frame updates). This is
what lets a trap tell the player script to take damage, a manager read every
enemy's health, or a cutscene freeze an NPC's logic without deleting it.
with_state! / with_state_mut! give typed, allocation-free access when the
state type is known. get_var! / set_var! / call_method! work dynamically by
member name and go through Variant, for generic tools, UI, and animation
events that do not know the concrete script type.
Use Cases
Situation
Choice
Why
Tradeoff
Known state type on self or another node
with_state! / with_state_mut!
Typed, allocation-free access with compiler-checked fields
Closure borrow must end before another ctx.run call
Trap asks one player to take damage
call_method!
Receiver owns damage rules and returns a result
Method name, argument order, and decode are runtime contracts
Tool knows volume by name, not state type
get_var! / set_var!
Dynamic member access fits adapters and tools
Strict type mismatch fails; it does not coerce asset paths
State member contains a dynamic node ref
get_node_var!
Decodes the node-ref member directly to NodeID
Missing/wrong member returns no usable target
Spawned node needs optional behavior selected at runtime
script_attach! / script_detach!
Script lifetime follows runtime composition
Attach path/build must exist; detach removes its owned state
Cutscene pauses one behavior without deleting data
update enable flags
State and node remain alive while callbacks stop
Signals/method calls may still reach the script; this is not full suspension
Context
Script context path: ctx.run
Module access: ctx.run.Scripts()
Lifecycle examples stay inside lifecycle! because script hooks get API from the macro expansion.
Practical Example
A spike-trap script reads its scene-wired player ref and calls take_damage.
The trap does not need to know the player's script type or #include it: the
call resolves the method by name at runtime and returns the player's typed reply
wrapped in a Variant.
#[State]structHazardState{// pub because the scene wires it via script_vars.#[expose]#[node_ref(Node2D,Node3D)]pubtarget:Option<NodeID>,}lifecycle!({fn on_update(&self, ctx:&mutScriptContext<'_,API>){let target = with_state!(ctx.run,HazardState, ctx.id, |state| state.target).unwrap_or_default();ifletSome(player) = target {let survived = call_method!(
ctx.run,
player,
method!("take_damage"),
params![25.0_f32]);// The called method returned a bool; decode the Variant reply.ifletSome(false) = survived.as_bool(){
signal_emit!(ctx.run, signal!("player_died"), params![]);}}}});
All three dynamic paths reach only members the target declares pub: get_var! / set_var! need a pub state field and call_method! a pub fn (any form β pub, pub(crate), ...). Non-pub members get no dispatch glue β get_var! returns Variant::Null, set_var! is ignored, call_method! returns Variant::Null. See state visibility and method visibility.
get_var! and call_method! return Variant because member lookup is dynamic.
The called method can still return a primitive such as bool, i32, f32, or String.
Generated script glue wraps that typed return into Variant.
Decode with as_*, parse::<T>(), or into_parse::<T>().
Add or replace one node's behavior from a runtime-selected script path. The new script gets default state, runs on_init synchronously, then joins queued on_all_init/update work.
Fails when / edge behavior
Returns false for a missing node, missing script constructor, or failed attach. No scene vars are accepted.
&mut self, script_id: NodeID, method: M, params: &[Variant],
Returns
Variant
Use when
Call self or another script dynamically by method name/hash; prefer direct Rust helper calls for known same-script logic.
Fails when / edge behavior
Returns Variant::Null when the script id, method, or params do not resolve. Non-pub methods have no dispatch glue and return Variant::Null. Primitive method returns are wrapped into Variant.
with_state
Field
Detail
Access
ctx.run.Scripts()
Signature
with_state!(ctx.run, state_ty, id, f)
Params
ctx, state_ty, id, f
Returns
Option<V> with the closure result
Use when
Use with_state to with state for runtime script composition; prefer typed state access when the concrete state type is known.
Fails when / edge behavior
Returns None for a missing ID or wrong state type.
with_state_mut
Field
Detail
Access
ctx.run.Scripts()
Signature
with_state_mut!(ctx.run, state_ty, id, f)
Params
ctx, state_ty, id, f
Returns
same as backing method
Use when
Use with_state_mut to with state mut for runtime script composition; prefer typed state access when the concrete state type is known.
Fails when / edge behavior
Uses the backing with_state_mut return and failure behavior unchanged; the wrapper adds no coercion or fallback.
script_attach
Field
Detail
Access
ctx.run.Scripts()
Signature
script_attach!(ctx.run, id, path)
Params
ctx, id, path
Returns
bool or () as shown by backing method
Use when
Macro form for path-based runtime attach/replacement; use an explicit init method after attach when post-on_init configuration is acceptable.
Fails when / edge behavior
Returns the backing attach bool; false means the node/script could not attach. No scene vars are applied.
script_detach
Field
Detail
Access
ctx.run.Scripts()
Signature
script_detach!(ctx.run, id)
Params
ctx, id
Returns
bool or () as shown by backing method
Use when
Use script_detach to script detach for runtime script composition; prefer typed state access when the concrete state type is known.
Fails when / edge behavior
Returns false when script_detach cannot apply to the supplied target or inputs; true confirms success.
script_set_update_enabled
Field
Detail
Access
ctx.run.Scripts()
Signature
script_set_update_enabled!(ctx.run, id, enabled)
Params
ctx, id, enabled
Returns
bool or () as shown by backing method
Use when
Use script_set_update_enabled to script set update enabled for runtime script composition; prefer typed state access when the concrete state type is known.
Fails when / edge behavior
Returns false when script_set_update_enabled cannot apply to the supplied target or inputs; true confirms success.
Use script_set_fixed_update_enabled to script set fixed update enabled for runtime script composition; prefer typed state access when the concrete state type is known.
Fails when / edge behavior
Returns false when script_set_fixed_update_enabled cannot apply to the supplied target or inputs; true confirms success.
get_var
Field
Detail
Access
ctx.run.Scripts()
Signature
get_var!(ctx.run, id, member)
Params
ctx, id, member
Returns
Variant
Use when
Use get_var to get var across runtime scripts; prefer typed state access when concrete state type is known.
Fails when / edge behavior
Returns Variant::Nil when get_var cannot resolve the requested dynamic member or call result, including fields not declared pub.
get_node_var
Field
Detail
Access
ctx.run.Scripts()
Signature
get_node_var!(ctx.run, id, member) -> NodeID
Params
ctx, id, member
Returns
NodeID
Use when
Use to read a node-ref script var (NodeScriptVar::NodeRef) back as a NodeID without manual Variant::as_node unwrapping.
Fails when / edge behavior
Returns NodeID::nil() when the var is missing or is not a node reference.
set_var
Field
Detail
Access
ctx.run.Scripts()
Signature
set_var!(ctx.run, id, member, value)
Params
ctx, id, member, value
Returns
bool or () as shown by backing method
Use when
Use set_var to set var across runtime scripts; prefer typed state access when concrete state type is known.
Fails when / edge behavior
Returns false when set_var cannot apply to the supplied target or inputs, including fields not declared pub; true confirms success.
call_method
Field
Detail
Access
ctx.run.Scripts()
Signature
call_method!(ctx.run, id, method, params)
Params
ctx, id, method, params
Returns
Variant
Use when
Use call_method to call method for runtime script composition; prefer typed state access when the concrete state type is known.
Fails when / edge behavior
Returns Variant::Nil when call_method cannot resolve the requested dynamic member or call result, including methods not declared pub fn.