## Animator As Crab A hard fork of [Animator As Code](https://github.com/hai-vr/av3-animator-as-code) where animator controllers are written in [Rhai](https://rhai.rs/) instead of C#. A Rhai script is evaluated by a Rust library (`libaac`), which validates it and emits the whole controller as JSON. A Unity Editor window deserializes that JSON and builds a real `AnimatorController` through the original Animator As Code V1 library, which is left untouched. ``` script.rhai --> libaac (Rust) --JSON--> AacCrabWindow (Unity Editor) --> AnimatorController ``` ## Layout | Path | Contents | | --- | --- | | `rust/` | The Rhai DSL, graph model, validator, and the `libaac` cdylib. | | `rust/examples/avatar.rhai` | The reference script, exercising every feature of the DSL. | | `csharp/dev.doloro.animator-as-crab/` | The Unity package: the untouched Animator As Code V1 library and the bridge in `V1/Editor/Crab/`. | | `flake.nix` | Dev shell with the Rust toolchain, `dotnet`, `mono`, and `jq`. | ## Building ```sh nix develop cargo test --manifest-path rust/Cargo.toml cargo run --bin aac-dump -- rust/examples/avatar.rhai # print the generated JSON nix build .#aac # libaac.so + aac-dump ``` Copy `libaac.so` (or `libaac.dll`, `libaac.dylib`) into the Unity project's `Assets/Plugins` folder, and add `csharp/dev.doloro.animator-as-crab` to the project's packages. ## Writing a script ```rhai let aac = AnimatorAsCode(); aac.system_name("MyAvatar"); aac.asset_key("AAC_"); let speed = aac.float_param("Speed", 0.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 walk_clip = aac.clip("walk_anim"); walk_clip.toggle("Body/Props", true); walk.set_clip(walk_clip); idle.transition_to(walk).when(speed > 0.1).no_exit_time().duration(0.25); ``` Conditions are written on the parameters themselves (`speed > 0.1`, `is_sitting == true`). There is no `&&` or `||` — Rhai's are short-circuit built-ins that cannot be overloaded — so use `when_all([speed < 0.05, is_sitting == false])`. See `rust/examples/avatar.rhai` for the full surface: parameters, clips, curves, blend trees, sub-state machines, any-state transitions, and transition settings. ## Generating Open *Tools > Animator As Crab* and fill in the window: - the path to the `.rhai` script (it is watched, so saving the script regenerates the controller), - the `AnimatorController` to generate into, - the animator root, the asset container, and the container mode, - whether states should write defaults. Nothing is defaulted silently, and the controller is rebuilt with Animator As Code's modification API: the controller is cleared, and the clips and blend trees of the same asset key are removed from the container before being recreated. Animator As Code's own C# API is untouched and still usable on the same controller. ## Limitations - The Unity side has not been run: there is no Unity project in this repository, so the bridge and the generator are verified by reading, not by executing. - Blend trees can only nest a blend tree that was declared earlier in the script. - The graph carries no avatar masks, layer weights, state behaviours, or parameter drivers yet.