テキストファイル(.animscript)を書くだけで、Unity の AnimatorController を自動生成するエディターツールです。 VRChat アバター(Avatar 3.0)での利用を想定しており、VRC Avatar Parameter Driver にも対応しています。
param Speed : float = 0
layer "Locomotion" default wd on {
state Idle = "Idle.anim"
state Walk = "Walk.anim"
entry -> Idle
Idle -> Walk when Speed > 0.1 dur 0.2
Walk -> Idle when Speed < 0.1 dur 0.2
}
これをビルドすると、パラメータ・レイヤー・ステート・遷移がすべて設定された .controller が出力されます。
build/ に出力。再ビルドしても GUID を維持(アバターに設定済みの参照が切れません)driver ブロックを使う場合のみ必須。無い環境では driver は警告付きでスキップされます.animscript ファイルをウィンドウに ドラッグ&ドロップ(または ObjectField から選択)build/スクリプト名.controller が生成されますSamples/ フォルダに実例が 4 本入っています(これらもそのままドキュメントです)// 行コメントが書けます
ファイルの上の方に書きます。Animator Controller の Parameters に追加されます。
param Speed : float = 0
param GestureLeft : int = 0
param Grounded : bool = true
float / int / boolwhen)で使うパラメータは 必ず宣言が必要 です(VRChat 標準の GestureLeft なども)+ や空白などの特殊文字を含める場合は、文字の前に \ を付けます。宣言・参照の両方で同じように書きます。param A\+B : float = 0
layer "Example" {
state Idle
state Active
entry -> Idle
Idle -> Active when A\+B > 0
}
\ はエスケープ記号なので、実際の Animator パラメータ名は A+B です。Importer も特殊文字を含むパラメータをこの形式で書き出します。
layer "Locomotion" default wd on loop off bl additive weight 1.0 {
...
}
| オプション | 意味 | 既定値 |
|---|---|---|
default | このレイヤーをコントローラの先頭にする | 最初のレイヤー |
wd on/off | レイヤー内ステートの Write Defaults 既定値 | on(Unity 標準) |
loop on/off | レイヤー内クリップの Loop Time 既定値 ※ | 変更しない |
bl additive/override | レイヤーのブレンディングモード | override |
mask "パス" | レイヤーに適用する AvatarMask(.mask) | なし |
weight 数値 | レイヤーウェイト | 1.0 |
複数レイヤーも書けます。default は1つだけ。
※
loop指定は クリップのアセット自体 の Loop Time を書き換えます(ビルド時に通知が出ます)。
state Idle = "Idle.anim" // クリップ指定
state Walk = "Walk.anim" speed 1.2 cycleOffset 0.25 time MotionTime mirror on footIK on wd off // オプション付き
state Locomotion = "BlendTrees/Locomotion.asset" // BlendTree もパスで指定可能
state Empty // 空ステート(motion 無し)
state Pose {
clip "Pose.anim" // BlendTree の .asset も指定可能。空にする場合は clip none
speed 1.0
speedParam SpeedMultiplier
cycleOffset 0.25
cycleOffsetParam CycleOffset
time MotionTime
mirror on
mirrorParam Mirror
footIK on
wd off
loop on
driver { ... }
}
| オプション | 意味 |
|---|---|
speed 数値 | ステートの再生速度 |
speedParam パラメータ名(sp と省略可) | 再生速度を制御するパラメータ |
cycleOffset 数値(co と省略可) | クリップの再生開始位置 |
cycleOffsetParam パラメータ名(cop と省略可) | クリップの再生開始位置を制御するパラメータ |
time パラメータ名 | Motion Time を制御するパラメータ |
mirror on/off | ステートのミラー再生 |
mirrorParam パラメータ名(mp と省略可) | ミラー再生を制御するパラメータ |
footIK on/off | Foot IK |
wd on/off(writeDefault とも書けます) | Write Defaults(レイヤー指定より優先) |
loop on/off | このクリップの Loop Time ※レイヤー指定より優先 |
driver { } | VRC Parameter Driver(下記) |
playableLayerControl { } | VRC Playable Layer Control |
animatorLayerControl { } | VRC Animator Layer Control |
trackingControl { } | VRC Animator Tracking Control |
locomotionControl { } | VRC Animator Locomotion Control |
temporaryPoseSpace { } | VRC Animator Temporary Pose Space |
{ は次の行に書いても OK(Allman スタイル)です。
ステートに入ったときにパラメータを書き換えます。
VRCAvatarParameterDriver としてステートにアタッチされます。
state ThumbsUp {
clip "ThumbsUp.anim"
driver localOnly {
set MyToggle 1 // Set(bool には true/false も可)
add MyFloat 0.5 // Add
random MyInt 0 10 // Random(最小 最大)
copy MyFloat -> MyInt // Copy(コピー元 -> コピー先)
}
}
localOnly を付けるとドライバーの Local Only が ON になりますparam 宣言されていない場合は 警告 が出ます(VRCExpressionParameters 側で管理する運用もあるため、エラーではなく警告です)同じステートに各ブロックを複数置けます。
state Control {
playableLayerControl {
layer FX
goalWeight 1
blendDuration 0.25
}
playableLayerControl {
layer Action
goalWeight 0
blendDuration 0.1
}
trackingControl {
head Animation
leftHand Tracking
rightHand Tracking
}
}
layer は Action / FX / Gesture / Additive、tracking の値は NoChange / Tracking / Animation です。trackingControl の未指定項目は SDK の既定値(NoChange)のままになります。
VRCAnimatorLayerControl は playable で対象Playable Layer、layer でサブレイヤー番号を指定します。
animatorLayerControl {
playable FX
layer 1
goalWeight 1
blendDuration 0.25
}
locomotionControl {
disableLocomotion true
}
temporaryPoseSpace {
poseSpace enter
fixedDelay false
delay 0.25
}
temporaryPoseSpace の poseSpace には enter / exit、fixedDelay には true / false を指定します。
entry -> Idle // 開始地点(デフォルトステート)
Idle -> Walk when Speed > 0.1 dur 0.25 offset 0.1 // 条件付き遷移
Idle -> Walk -> Run -> Idle // チェーン(A→B→C と順に作られる)
Idle -> Walk -> Run -> Idle exitTime 0.95 // ↑先頭に戻れば「ループ」
Walk -> exit exitTime 0.95 dur 0.1 // Exit へ抜ける
any -> Idle when GestureLeft == 0 // AnyState から
any -> Idle self // self … 自分自身への遷移も許可
| オプション | 意味 |
|---|---|
when 条件 | 遷移条件(and で複数指定可) |
exitTime 数値 | Exit Time。書くと HasExitTime が ON、書かなければ OFF |
dur 数値 | 遷移時間(秒) |
offset 数値 | 遷移先クリップの再生位置オフセット |
self | AnyState 遷移で canTransitionToSelf を ON(any からのみ) |
when Grounded // bool が true のとき
when !Grounded // bool が false のとき
when Speed > 0.1 // > < == != が使えます(>= <= は無し)
when Speed > 0.1 and Grounded // and … 両方満たす
when GestureLeft == 2 or GestureLeft == 3 // or … どちらか満たす
when (A or B) and (C or D) // 括弧でのグルーピングも可
and は or より優先されます(A or B and C = A or (B and C))or は内部で複数の遷移に展開されます(Unity の遷移条件は AND のリストしか持てないため)
A -> B when X or Y → A -> B [X] と A -> B [Y] の2本の遷移(A or B) and (C or D) → 4本の遷移[1] [2] のような番号が付きます!(A or B) のような括弧ごとの否定は使えません(!A and !B のように分解してください)>= / <= は 使えません(Unity の AnimatorCondition に無いため)。> < で書き直してくださいコントローラには出力されない、ビルド専用の変数です。
var count = 4 // 宣言($ は付けない)
count = $count + 1 // 代入(参照するときは $count と書く)
数値を書ける場所ではどこでも計算式が使えます(+ - * / % と ())。
param Max : int = $count * 2
state Pose = "pose.anim" speed 1.0 + 0.5
範囲を指定して中身をくり返し展開します(両端を含みます)。
for i in 0..7 {
state Pose$i = "Gestures/Left_$i.anim"
Idle -> Pose$i when GestureLeft == $i dur 0.1
Pose$i -> Idle when GestureLeft != $i dur 0.1
}
step で刻み幅を変えられます:for i in 0..10 step 2 { }(負の step も可)$i のように $ を付けて参照します条件が成り立つ間、中身をくり返し展開します。
var i = 0
while $i < $count {
state Item$i = "Menu/Item$i.anim"
i = $i + 1 // カウンタの更新を忘れずに!
}
== != < > <= >= がすべて使えます(自分たちで評価するため)$変数名 はステート名・クリップパス・パラメータ名など、文字列や名前の中にも書けます。
for i in 0..3 {
state Pose$i = "clips/pose_$i.anim" // Pose0, Pose1, ... ができる
}
$$ と書くと $ そのものになります(例: "price_$$.anim" → price_$.anim)state に書いた文字列は、次の優先順位で探します。
state Idle = "Animations/Idle.anim"(.anim は省略可)state Idle = "Assets/Anims/Idle.anim" または state Idle = "Packages/com.example.package/Anims/Idle.anim"state Idle = "Idle"(/ を含まない場合。fbx 内のクリップも対象)同じ名前のクリップが複数見つかった場合は、候補一覧付きのエラーになります。パスで指定してください。
Animator Controller 内に直接埋め込まれている BlendTree は、Importer で変換するとスクリプトと同じフォルダの AnimScript/コントローラー名/ に .asset として書き出され、そのファイルが state から参照されます。ネストされた BlendTree も含めて複製されます。
build/スクリプト名.controllerビルドに失敗すると、ウィンドウ下部と Unity コンソールに行番号付きで表示されます。
主なエラー:
| メッセージ | 原因 |
|---|---|
| パラメータ「X」は宣言されていません | when で使うパラメータは param 宣言が必要 |
| ステート「X」はレイヤー「Y」に定義されていません | 遷移先のスペルミス、または state 宣言忘れ |
| 「>=」は遷移条件には使えません | > < で書き直してください |
| while が 512 回を超えました | カウンタ変数の更新忘れ(無限ループ) |
| 変数「X」は宣言されていません | var で宣言してから $x で参照してください |
主な警告(ビルドは成功します):
when または exitTime を指定してくださいstate layer param for while entry exit any when など)と同じ名前のステートは作れません.asset などのアセットパスで指定できます(名前検索は AnimationClip のみ)loop on/off はクリップのアセット自体を変更します(他の Animator とも共有される点に注意)Tools > ぷこのつーる > AnimScript Builder の「コントローラからインポート」、または Project ウィンドウで AnimatorController を右クリック → AnimScript/animscript に変換 から使えます。
Project ウィンドウで .animscript ファイルを右クリックし、AnimScript > AnimScriptをビルド確認 を選ぶと、AnimatorController を生成せずにスクリプトの解析・検証を実行できます。
.animscript を編集してUnityが再インポートすると、同じ解析・検証が自動実行されます。エラーや警告はConsoleに行番号付きで表示されます。
AnimatorController (.controller)
│
▼
.animscript (テキスト)
<コントローラ名>.animscript が作成されます.animscript に書き出されますstate として展開されます。次のコメントで範囲を示します
// ここから先はサブステート「XXX」の内部です
// サブステート終了ですA B → A_B など)詳しい内部構造は ARCHITECTURE.md を参照してください。
Packages/net.puk06.animscript/
├── Editor/
│ ├── AnimScriptBuilderWindow.cs … ウィンドウ UI
│ ├── SyntaxCheatSheet.cs … ウィンドウ内チートシート
│ ├── Importer/ … コントローラ → animscript 逆変換
│ │ ├── ControllerImporter.cs
│ │ ├── DriverExporter.cs
│ │ ├── NameSanitizer.cs
│ │ ├── ScriptTextWriter.cs
│ │ └── ImportMenuItem.cs
│ ├── Language/ … 言語フロントエンド(Unity 非依存)
│ │ ├── Lexer.cs … 字句解析
│ │ ├── Parser.cs … 構文解析
│ │ └── Ast/ … AST ノード
│ ├── Compiler/ … コンパイル・生成
│ │ ├── AstExpander.cs … for/while/var の展開
│ │ ├── ScriptValidator.cs … 意味チェック
│ │ ├── AnimatorCompiler.cs … 生成の統括
│ │ └── Builder/ … State/Transition/Driver 等
│ └── Util/
│ ├── AnimScriptPaths.cs … 出力パス周り
│ └── GuiHelper.cs … ウィンドウ用の小物
└── Samples/ … 実例サンプル(01〜04)
処理の流れ:Lexer → Parser → AstExpander → ScriptValidator → ClipResolver → 生成 の順です。
net.puk06.animscript
未設定
0.10.0
2022.3 以降
なし
なし
未設定