83 lines
3.2 KiB
Markdown
83 lines
3.2 KiB
Markdown
## 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.
|