| Header | Link |
|---|---|
| Purpose | Purpose |
| Use Cases | Use Cases |
| Example | Example |
| Reference | Reference |
Perro animation has two resource files and two scene nodes that together let you play authored motion instead of scripting transforms by hand. Use a single .panim clip through an AnimationPlayer for one-off motion (a door, a chest, a taunt), or mix many clips through a .panimtree graph and an AnimationTree node when a character needs speed blends and aim layers. This page is the map that tells you which of the four pieces to reach for.
- One-shot prop or UI motion:
AnimationPlayerwith a single.panimandplayback = oncefor a door swing or reward popup. - Looping ambient motion:
AnimationPlayerwithplayback = loopfor a spinning fan or bobbing pickup. - Full character locomotion:
AnimationTree+.panimtreeblendingIdle/Run/Aimslots, driven live withanim_tree_set_weight!. - Rebinding one clip to different rigs: reuse the same
.panimobject name (@Hero) but pointbindingsat a different scene node per slot entry. - Scripted playback control:
anim_player_play!,anim_player_seek_frame!, andanim_tree_play_slot!start, scrub, and retime clips from gameplay code.
Use AnimationPlayer for one clip timeline on known targets. Use
AnimationTree when gameplay continuously blends slots/layers. Keep gameplay
truth in script state: animation events may notify contact frames, but a visual
timeline should not become the sole owner of health, inventory, or win state.
A single looping clip driven by an AnimationPlayer:
[PlayerRoot]
[Node3D/]
[/PlayerRoot]
[IdlePlayer]
[AnimationPlayer]
animation = "res://animations/idle.panim"
bindings = { Hero = @PlayerRoot }
playback = loop
[/AnimationPlayer]
[/IdlePlayer]let clip = animation_load!(res, "res://animations/idle.panim");
let _ = anim_player_set_clip!(ctx, player, clip);
let _ = anim_player_bind!(ctx, player, "Hero", hero);
let _ = anim_player_seek_frame!(ctx, player, 0);
let _ = anim_player_play!(ctx, player);For the multi-clip blend path, see the AnimationTree section below and .panimtree Format.
Perro animation has two resource files and two scene nodes.
Sigils:
-
$=> value var define/use. -
scenes:
@NodeKey=> scene node ref. -
.panim:[Objects]declares bare names (Hero = Node3D), frame blocks ref them as@Hero. -
.panimtree: graph blocks declare bare names ([MoveBlend]), graph inputs ref graph nodes or slots as@MoveBlend,@Idle. -
scene
AnimationPlayer/AnimationTreebindings map object names to scene node refs with@NodeKey. -
.panim: one animation clip. -
.panimtree: one animation graph. -
AnimationPlayer: plays one.panim. -
AnimationTree: mixes many.panimclips through one.panimtree.
Use .panim for raw clip data.
It declares animation object names in [Objects].
Those names are clip-local track keys.
They are not scene node names.
[Animation]
name = "Idle"
fps = 30
[/Animation]
[Objects]
Hero = Node3D
[/Objects]
[Frame0]
@Hero {
position = (0, 0, 0)
}
[/Frame0]@Hero is the animation object.
Scene binding maps Hero to a real scene node.
Full format: .panim Format.
Use AnimationPlayer when one clip drives one set of bindings.
[PlayerRoot]
[Node3D/]
[/PlayerRoot]
[IdlePlayer]
[AnimationPlayer]
animation = "res://animations/idle.panim"
bindings = { Hero = @PlayerRoot }
speed = 1.0
paused = false
playback = loop
[/AnimationPlayer]
[/IdlePlayer]animation loads one .panim.
bindings maps .panim [Objects] names to scene nodes.
Binding values must use @NodeKey (or a var such as $root that resolves to one).
Runtime API:
let clip = animation_load!(res, "res://animations/idle.panim");
let _ = anim_player_set_clip!(ctx, player, clip);
let _ = anim_player_bind!(ctx, player, "Hero", hero);
let _ = anim_player_seek_frame!(ctx, player, 0);
let _ = anim_player_play!(ctx, player);Runtime docs: Animations Module.
Use .panimtree for static graph shape.
It owns:
- slot names
- graph node keys
Blend,Add,Invert- default weights
- masks
- required
Output
It does not own actual scene node bindings.
It does not own runtime playback state.
[AnimationTree]
name = "PlayerLocomotion"
[/AnimationTree]
[AnimationSlots]
Idle
Run
Aim
[/AnimationSlots]
[MoveBlend]
[Blend]
inputs = [@Idle, @Run]
weights = [1.0, 0.0]
mask = { objects=[Hero], fields=[position, rotation, scale] }
[/Blend]
[/MoveBlend]
[AimAdd]
[Add]
base = @MoveBlend
inputs = [@Aim]
weights = [0.75]
mask = { objects=[Hero], bones=[Spine, Chest] }
[/Add]
[/AimAdd]
[Output]
input = @AimAdd
[/Output]Blend mixes any number of inputs.
[MoveBlend]
[Blend]
inputs = [@Idle, @Walk, @Run]
weights = [0.0, 0.35, 0.65]
[/Blend]
[/MoveBlend]Add applies additive deltas to a base.
[UpperBodyAdd]
[Add]
base = @MoveBlend
inputs = [@Aim, @Recoil, @Breath]
weights = [1.0, 0.45, 0.2]
[/Add]
[/UpperBodyAdd]Invert flips a delta for subtractive layers.
[AimSubtract]
[Invert]
input = @Aim
[/Invert]
[/AimSubtract]Output is required.
Full format: .panimtree Format.
Use AnimationTree when many clips combine into one final pose.
The scene node supplies:
tree: loaded.panimtreeanimations: clips bound by slot order- per-slot clip object bindings
speedpaused
[Hero]
[Node3D/]
[/Hero]
[HeroAnimTree]
[AnimationTree]
tree = "res://animations/player.panimtree"
animations = [
{ animation = "res://animations/idle.panim", bindings = { Hero = @PlayerRoot }, playback = loop, speed = 1.0, paused = false },
{ animation = "res://animations/run.panim", bindings = { Hero = @PlayerRoot }, playback = loop, speed = 1.0, paused = false },
{ animation = "res://animations/aim.panim", bindings = { Hero = @PlayerRoot }, playback = boomerang, speed = 1.0, paused = false },
]
speed = 1.0
paused = false
[/AnimationTree]
[/HeroAnimTree]Slot mapping comes from .panimtree [AnimationSlots].
If [AnimationSlots] is Idle, Run, Aim, then:
animations[0]feedsIdleanimations[1]feedsRunanimations[2]feedsAim
Each slot entry can bind the same .panim object name to a different scene node.
Each slot entry can set playback, speed, and paused.
playback accepts once, loop, or boomerang.
Slot speed multiplies tree speed.
Runtime API:
let run = animation_load!(res, "res://animations/run.panim");
let _ = anim_tree_set_clip!(ctx, tree, "Run", run);
let _ = anim_tree_play_slot!(ctx, tree, "Run");
let _ = anim_tree_seek_slot_frame!(ctx, tree, "Run", 0);
let _ = anim_tree_set_slot_speed!(ctx, tree, "Run", 1.25);
let _ = anim_tree_set_slot_playback!(ctx, tree, "Run", AnimationPlaybackType::Loop);
let _ = anim_tree_set_weight!(ctx, tree, "MoveBlend", "Run", 1.0);
let _ = anim_tree_pause!(ctx, tree, false);Slots accept name or index.
Node and input names omit @ in Rust API, that's just for .panim and .panimtree files
Bad refs return false.
Runtime node trees: Node Collections.