aac.AnimationStore(folder) seeds a clip from an existing .anim asset and returns a normal ClipBuilder, so pre-made clips work anywhere generated clips do and can still be edited (looping, keyframes, toggles, blend shapes). The Unity side clones the asset into the container and applies the script's changes to the clone, leaving the original untouched. - ClipData gains optional source; looping becomes Option<bool> so an untouched store clip keeps the asset's own looping setting. - Add rust/examples/animation_store.rhai, a worked store example.
67 lines
2.3 KiB
Plaintext
67 lines
2.3 KiB
Plaintext
// An Animator Controller described as Rhai.
|
|
//
|
|
// cargo run --bin aac-dump -- rust/examples/avatar.rhai
|
|
//
|
|
// Combine conditions with `when_all([...])`: Rhai's `&&` cannot be overloaded, so
|
|
// `when(a > 0.1 && b)` is not valid.
|
|
|
|
let aac = AnimatorAsCode();
|
|
aac.system_name("MyAvatar");
|
|
aac.asset_key("AAC_");
|
|
|
|
let speed = aac.float_param("Speed", 0.0);
|
|
let is_sitting = aac.bool_param("IsSitting", false);
|
|
let gesture = aac.int_param("Gesture", 0);
|
|
|
|
let ctrl = aac.new_controller();
|
|
let base = ctrl.layer("Base");
|
|
|
|
let idle = base.state("Idle", 0, 0);
|
|
let walk = base.state("Walk", 1, 0);
|
|
let run = base.state("Run", 2, 0);
|
|
let sit = base.state("Sit", 0, 1);
|
|
|
|
let idle_clip = aac.clip("idle_anim");
|
|
idle_clip.looping(true);
|
|
idle_clip.keyframe("Body/Hand", "m_IsActive", 0.0, 1.0);
|
|
idle_clip.blend_shape("Body", "Smile", 0.0, 0.0);
|
|
idle_clip.blend_shape("Body", "Smile", 1.0, 0.8);
|
|
|
|
let walk_clip = aac.clip("walk_anim");
|
|
walk_clip.looping(true);
|
|
walk_clip.toggle("Body/Props", true);
|
|
|
|
let run_clip = aac.clip("run_anim");
|
|
run_clip.looping(true);
|
|
run_clip.toggle("Body/Props", false);
|
|
|
|
// A pre-made clip: it is cloned into the container at generation time, so it can be edited here
|
|
// without touching the asset stored in Assets/Doloro/Clips.
|
|
let store = aac.AnimationStore("Assets/Doloro/Clips");
|
|
let crouch_clip = store.clip("Crouch");
|
|
crouch_clip.looping(true);
|
|
crouch_clip.toggle("Body/Props", true);
|
|
sit.set_clip(crouch_clip);
|
|
|
|
idle.set_clip(idle_clip);
|
|
walk.set_clip(walk_clip);
|
|
|
|
let locomotion = aac.blend_tree("locomotion");
|
|
locomotion.simple_1d(speed);
|
|
locomotion.add_motion(walk_clip, 0.0);
|
|
locomotion.add_motion(run_clip, 5.0);
|
|
run.set_motion(locomotion);
|
|
|
|
idle.transition_to(walk).when(speed > 0.1).no_exit_time().duration(0.25);
|
|
walk.transition_to(run).when(speed > 4.0).no_exit_time().duration(0.25);
|
|
run.transition_to(walk).when(speed < 4.0).no_exit_time().duration(0.25);
|
|
walk.transition_to(idle).when_all([speed < 0.05, is_sitting == false]).duration(0.25);
|
|
|
|
base.any_state().transition_to(sit).when(is_sitting == true).no_exit_time().duration(0.2);
|
|
|
|
let gestures = base.sub_machine("Gestures", 2, 0);
|
|
let peace = gestures.state("Peace", 0, 0);
|
|
let point = gestures.state("Point", 1, 0);
|
|
peace.transition_to(point).when(gesture == 1).duration(0.1);
|
|
point.transition_to(peace).when(gesture == 0).duration(0.1);
|