No description
  • C# 76.1%
  • Rust 17.6%
  • Lua 4%
  • Shell 1.2%
  • Nix 0.8%
  • Other 0.3%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-09-22 20:26:25 +00:00
.gitea/workflows remove continuous release workflow and version entry 2026-09-19 18:23:21 +01:00
.github shity basic one shot 2026-09-18 14:01:10 +01:00
csharp vpm lock.. 2026-09-22 21:25:26 +01:00
rust vpm lock.. 2026-09-22 21:25:26 +01:00
types meow 2026-09-22 18:48:52 +01:00
vpm vpm: index for v0.3.3 2026-09-22 20:26:25 +00:00
.envrc stuff 2026-09-19 18:24:12 +01:00
.gitignore lsp support 2026-09-22 15:11:43 +01:00
.luarc.json lsp support 2026-09-22 15:11:43 +01:00
AGENTS.md meow 2026-09-22 18:48:52 +01:00
DOCUMENTATION.md fixes 2026-09-21 10:47:32 +01:00
flake.lock shity basic one shot 2026-09-18 14:01:10 +01:00
flake.nix meow 2026-09-21 10:11:40 +01:00
justfile fixes 2026-09-21 10:47:32 +01:00
LICENSE Update LICENSE: 2024-07-01 23:21:17 +02:00
MigratingFromV0ToV1.md (PACKAGING) Change the folder structure for package format 2023-10-02 04:53:27 +02:00
old_README.md new read me 2026-09-18 13:06:03 +01:00
README.md meow 2026-09-21 10:11:40 +01:00
WRITING_SCRIPTS.md meow 2026-09-21 10:11:40 +01:00

Animator As Crab

A hard fork of Animator As Code where animator controllers are written in Lua instead of C#.

A Lua 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.lua --> libaac (Rust) --JSON--> AacCrabWindow (Unity Editor) --> AnimatorController

Layout

Path Contents
rust/ The Lua DSL, graph model, validator, and the libaac cdylib.
rust/examples/avatar.lua 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

nix develop
cargo test --manifest-path rust/Cargo.toml
cargo run --bin aac-dump -- rust/examples/avatar.lua    # 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

local aac = AnimatorAsCode()
aac:system_name("MyAvatar")
aac:asset_key("AAC_")

local speed = aac:float_param("Speed", 0.0)
local ctrl = aac:new_controller()
local base = ctrl:layer("Base")

local idle = base:state("Idle", 0, 0)
local walk = base:state("Walk", 1, 0)

local walk_clip = aac:clip("walk_anim")
walk_clip:toggle("Body/Props", true)

walk:set_clip(walk_clip)
idle:transition_to(walk):when(speed:gt(0.1)):no_exit_time():duration(0.25)

Conditions are written as method calls on the parameters themselves (speed:gt(0.1), is_sitting:eq(true)). To combine multiple conditions use when_all({speed:lt(0.05), is_sitting:eq(false)}).

See rust/examples/avatar.lua for the full surface: parameters, clips, curves, blend trees, sub-state machines, any-state transitions, and transition settings.

Pre-made clips (animation store)

An animation store seeds clips from AnimationClip assets that already exist in the project. store:clip(name) resolves to <folder>/<name>.anim and returns a motion usable anywhere a generated clip is: as a state motion, as a blend tree child, or through add_motion_direct. A store clip can be edited like any other clip.

local store = aac:AnimationStore("Assets/Doloro/Clips")
local walk = store:clip("Walk")          -- Assets/Doloro/Clips/Walk.anim
walk:looping(true)
walk:keyframe("Body/Props", "m_IsActive", 0.0, 0.0)
walk_state:set_clip(walk)
locomotion:add_motion(walk, 0.0)

The generator loads the asset with AssetDatabase.LoadAssetAtPath, clones it into the asset container, and applies the script's keyframes and looping on the clone: the pre-made asset is never modified. A store clip with no looping(...) call keeps the source asset's own looping setting. Requesting the same asset twice reuses the one reference, and a missing asset is a clear error.

Generating

Open Tools > Animator As Crab and fill in the window:

  • the path to the .lua 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.