mcpField
R
roblox-animation

roblox-animation

github.com/syphodev-ytクリエイティブ・メディア11952 回インストール4 日前に更新
リポジトリ

roblox-animation について

roblox-animation は、Roblox キャラクターのアニメーションを時間ごとのポーズデータとして作成し、書き出し前にレンダリングして確認するスキルです。Blender のリグを扱う制作者向けで、数値検証とフレーム単位の目視確認を組み合わせます。

主な機能

  1. 01JSON のポーズデータで仕様を作成
  2. 02リグ制御と FK 軸のキャリブレーション
  3. 03確認用フレームとコンタクトシートのレンダリング
  4. 04関節位置とリグ整合性の検査
  5. 05アニメーションを Roblox Luau に変換

活用シーン

  1. 01Roblox の戦闘モーションを作成・反復
  2. 02反応しないリグ制御や IK/FK 設定を診断
  3. 03参照画像とレンダリングポーズを比較
  4. 04Blender アニメーションを Roblox 向けに準備

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/syphodev-yt/roblox-ai-skills --skill roblox-animation

インストール後、Claude Code で/roblox-animationを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

LOCAL.template.md
references/
example-fk-punch.json
example-fk-roundhouse.json
example-fk-wave.json
example-uppercut.json
pose-recipes.md
studio-binder.lua
traps.md
scripts/
anim_render.py
calibrate_rig.py
fk_crouch.py
fk_probe.py
probe_bone.py
r6_clip.py
r6_joint.py
r6_luau.py
rbx_axis_check.py
sweep_control.py
to_roblox.py
upload_animation.py
scripts/luau/
dump_kfs.luau

詳細

Roblox アニメーション、ヘッドレス

このマシンで初めて作業する場合 このフォルダーの LOCAL.md を読んでください。存在しない場合は、 roblox-skills-setup スキルを実行するか、LOCAL.template.md を LOCAL.md にコピーして記入してください。 LOCAL.md にはパスとツールの場所が記載されています。これは自分専用で、共有されることはありません。

アニメーションをデータ(時間ごとのポーズを記述した JSON 仕様)として作成し、実際の Blender Action に焼き込み、レンダリングして、信じる前に結果を確認してください。

作業の流れは、作成 → 全フレームをレンダリング → コンタクトシートにタイル表示 → 確認 → 修正 → 繰り返しです。ここにあるものはすべて、この流れのどこかの手順で、ほかのチェックでは見つからなかった問題が検出されたことを受けて作られています。

まずここを読む:最も時間を無駄にする落とし穴

ほとんどの Roblox リグには、レストポーズを保持する Blender Action が同梱されています。 Blender はレンダリング時にその Action を再評価します。そのため、ポーズ値を設定してレンダリングすると:

  • すべての数値プローブでは、ポーズが正しく適用されたと報告されます
  • すべてのレンダリングフレームでは、リグがデフォルトのポーズを示します
  • データと画像は一致せず、エラーも発生しません

Action をクリアしても解決しません。なぜなら、その Action がレストポーズそのものだからです — クリアすると、手足が胴体に崩れ落ちます。

解決策:同じ Action にキーフレームを挿入し、フレームごとに frame_set() を呼び出してレンダリングします。 こうすればアニメーション自体が Action となり、上書きされることはありません。変更していないボーンは定数外挿によってレスト値を保持し、最終的に実際の Action が得られます。これは Roblox へのエクスポートに必要なものでもあります。scripts/anim_render.py ではすでにこの処理を行っています。

全リストは references/traps.md にあります。落とし穴は 28 個です。デバッグを始める前に読んでください。

IK ではなく FK で作成する

Roblox の KeyframeSequence は、各 Motor6D に 1 つずつ対応する、関節ごとの回転をまとめたツリー構造です。これは FK です。すべての R15 リグには、対応する関節ごとに 1 つの制御ボーンが用意されています。IK ターゲットでキャラクターを動かすと、Roblox が求めていないソルバーを経由して変換することになり、次のような代償が生じます:

  • 位置のみの IK ターゲットでは、手足のロールが自由なままになります。そのため、ブロック状の Roblox パーツはソルバーが選んだ面を表示し、フレーム間で急に切り替わります。テクスチャ付きのアバターでは、これが色が瞬時に変化するように見えます。これはアニメーションにバグがあるように見せる症状です
  • ソルバーがフレームごとに同等の解の間を飛び移るため、各フレームの検証には問題がなくても、手足が跳ねます
  • 処理が遅いです

FK には分岐も特異点もロールの曖昧さもなく、角度は正確に 1:1 で、Roblox にそのままエクスポートできます。

ほとんどのリグは IK モードで同梱されているため、FK_* ボーンはすべて反応しないように見えます。FK が機能しないと判断する前に、切り替えてください:

"properties": {"ARM_IK_FK.L": 0.0, "ARM_IK_FK.R": 0.0,
               "LEG_IK_FK.L": 0.0, "LEG_IK_FK.R": 0.0}

無料のコミュニティ製 R15 リグで測定したところ、規則性がありました。すべての手足はまっすぐ下向きに静止し、すべての FK_* ボーンでX の負方向は前方へ、Z の正方向はキャラクターの右側へ振れます。角度は 1:1 で、左右で同一です。ミラー反転はありません。子の角度は親に対する相対値です。

一般的な教訓は、どんなリグでも同じです。制御ボーンが反応しない場合、使えないと判断する前に、それを無効にするスイッチがないか確認してください。 Rigify 形式の R15 リグには、デフォルトが 1.0(IK)の ARM_IK_FK / LEG_IK_FK カスタムプロパティがあります。これを 0.0 に設定し、キーフレームを設定して(frame_set で元に戻らないようにします)、FK で作成してください。上記の方向規則は 1 つのリグで測定したものです。calibrate_rig.py と sweep_control.py でお使いのリグを再測定できるので、まだ使ったことのないリグでは実行してください。 お使いのリグの .blend パスは LOCAL.md に記入します。

手足を正確なワールド座標に到達させる必要がある場合に限り、IK を使用してください。その場合は落とし穴 12〜15 を読んでください。

参考ではなく、Robloxらしく見せる

  • 30 FPSで、格闘技の動きは0.3~0.7秒で行います。Animation Editor のデフォルトは 30fps です。現実の動作のタイミングは、ゲームには遅すぎます。動きの仕組みは実際の動作から取り入れ、タイミングは Roblox に合わせます。
  • 5つのポーズ:待機、予備動作、接触、フォロースルー、回復。
  • セグメントごとにイージングを設定します。打撃に向けて加速するには "ease": "in"、動きを落ち着かせるには "out" を使います。固定の smoothstep では、すべてのキーフレームに向けて減速するため、打撃は接触フレームで停止するようにイージングされ、動き全体がぼやけて見えます。
  • 誇張します。 Roblox の実際の格闘アニメーションでは、人間の可動域を大きく超える動きをさせ、シルエットからも読み取れるようにします。
  • 単色のグレーでレンダリングします("plain": true)。アバターのテクスチャが複雑だと、ブロック状のリグが見分けにくい塊になり、ポーズではなく衣装のデバッグに時間を取られます。Roblox のアニメーションが、まさにこの理由から無地のダミーで紹介されているのもそのためです。

references/pose-recipes.md に実際の数値があります。ガード、予備動作、構え、接触、フォロースルーの角度を測定した表、タイミングのひな形、そして見落としやすい2つのルール(肩と肘の合計は約120以下にすること、高い蹴りでは UpperLeg X を −120 より大きくしないと脚が胴体に埋もれること)が記載されています。これらを出発点に、プレビューを見ながら調整してください。数値を再導出しないでください。

速く作る — 推測ではなく計測する

一連の作業は数秒で完了します。1回の処理に何分もかかるなら、何かが間違っています。 中程度の性能の PC で、24~36フレームのアニメーションを1つ測定した結果です。

stagetimenotes
Blender がリグを読み込む0.7s起動が問題になることはありません
数値プローブ(FK コントロールマップ全体)0.1s数値でリグの状態を確認します
プレビューのレンダリング("preview": true)4~6.5s1ビュー、320x240、1サンプル
フルレンダリング、2ビュー @ 640x5609~17s最後に一度だけ実行します
GIF のエンコード0.3s
to_roblox.py → Luau0.1s
Studio でのビルドと検証execute_luau の呼び出し1回

Studio 内で完成するアニメーションのマシン処理時間は、1分を大きく下回ります。 実際に時間がかかるのは作成の反復作業です。そのため、プレビューに時間を使い、フルレンダリングには使わないでください。references/pose-recipes.md を出発点にすれば、2つ目の動きはプレビュー1~3回で完成するはずです。references/ のパンチは最初の試行で決まりました。一方、手を頭に当てているようにしか見えなかった波の例は、数値上はすべて合格していたにもかかわらず、そうではありませんでした。見た目で判断するには人間の目が必要で、2026-10-23 に修正されました。数値で証明できるのはポーズが仕様に合っていることです。その仕様が適切な動きを表しているかどうかを証明できるのは、実際に見ることだけです。

"report": true を指定すると、各拍のすべての関節の位置が出力されます。ポーズがおかしく見えるとき、レンダリングを5回繰り返して推測する代わりに、1回の実行で該当する関節がわかります。

プローブで答えられる質問に答えるために、レンダリングしないでください。

必須事項

どれも、省略した結果、見た目には問題がなさそうなのに壊れたものを出荷してしまったため、ここに記載しています。

  1. 終了コードが0でも信用しないでください。 anim_render.py はフレームごとにリグの整合性を検証し、フレームが書き出されたことも確認します。問題があれば、ゼロ以外のコードで強制終了します。
  2. フレームを確認してください。 毎回行います。
  3. 参照画像がある場合は、並べて比較できる画像を作り、それを基に判断してください。レンダリングだけを見て判断してはいけません。
  4. エンコード元の PNG ではなく、完成した GIF 自体を確認してください。
  5. 赤信号を青信号に変えるために、許容値を緩めないでください。 仕様を修正してください。

ワークフロー

1. リグをキャリブレーションする(まだ使ったことのないリグの場合)
blender --background <rig>.blend --enable-autoexec --python scripts/calibrate_rig.py
blender --background <rig>.blend --enable-autoexec --python scripts/sweep_control.py -- FK_UpperLeg.R:rot TORSO:rot

calibrate_rig.py は、変形用アーマチュアとコントロール用アーマチュア、Action に関する落とし穴、IK/FK 切り替え状態、実際に何かを動かすコントロールを報告します。 sweep_control.py は、各軸の方向、符号、有効範囲を示します。ボーンの位置だけでなく向きも測定するため、回転のみのコントロールも見逃しません。

FK_* ボーンが反応しない場合は、リグが壊れているのではなく、IK/FK の切り替えが原因です。

2. 仕様を作成する

fps、duration、w、h、margin、views、properties、plain、preview、 report、および {t, ease, bones: {Bone: {rot|loc|target|aim}}} 形式の keyframes[]。

ほとんどの場合、使うのは rot です。エンドエフェクターのないコントロール (ROOT)には loc を使います。target / aim は IK の最終手段です。落とし穴 12~15 を参照してください。

忘れると毎回問題になる点が 3 つあります。

  • FK では子の角度が親の角度に加算されます。 肩が 50°、肘が 70°だと、前腕は垂直から 120°傾き、肩の上を向きます。ガード姿勢では肩と肘の合計を約 110°未満にしてください。
  • 傾きとひねりは UpTorso に加えます。 ここが上半身のみを動かします。TORSO を動かすと脚も動くため、傾けるとフィギュアが倒れ、接地した足が滑ります。また、このリグには動きを増幅する特性があります。X = +15 で頭が 23°動きます。
  • 支持側の足首は逆回転させてください。 FK_Foot.X ≈ -(FK_UpperLeg.X + FK_LowerLeg.X) としないと、脚と一緒に足が傾き、キャラクターが斜面に立っているように見えます。

references/example-fk-roundhouse.json(0.8 秒のキック)、references/example-fk-punch.json(0.5 秒のクロス)と、references/pose-recipes.md を参照してください。

2a. 小道具を手に持たせる場合は、まず実際の持ち方を調べてください。

この手順はキーフレームを作成する前に行います。省略はできません。 クリップに武器やツールが登場した時点で、「ポーズが伝わるか」はリグの問題ではなく、その物体に関する問題になります。それは現実世界に関する事実であり、行列から推測できるものではありません。

実際の制作で、この手順が防ぐ失敗がありました。グレイブの頭を使い手の腰の位置で下向きにして作成したのです。その後のすべての工程は完璧に機能しました。エンジンは作成された持ち方を再現し、ポーズストリップはコンタクトシートの各フレームと完全に一致し、グリップ誤差は 0.000、武器が身体に入り込んだサンプルはゼロでした。それでもゲームには、逆さまに持たれた長柄武器が実装されました。ここで作成したポーズが間違っていても、その後のチェックはすべて、これとの一致を測定しているため、間違いを検出できません。 人間がようやく確認したとき、逆さまだと判定されました。その判断は正しく、わずか 10 秒の判断ミスが原因で、後続工程の作業セッション全体が無駄になりました。

作成する前に、次のことを行ってください。

  1. その種類の武器がどのように運ばれ、使われるのかを調べます。 コンセプトアートやほかのゲームではなく、実践者の写真を確認してください。数値を 4 回推測するより、10 秒調べるほうが確実です。
  2. 答えを _intent として仕様に記述します。 武器についての説明文にしてください。「頭を上にし、柄を前側の肩に渡す」「下げた手から刃を斜め上前方に向ける」などです。この説明文を基準にコンタクトシートを評価します。手順 3 を参照してください。
  3. 検索する前に、以下の一覧から明らかなものを確認します。
種類静止時振るとき
長柄武器、グレイブ、薙刀、槍頭を上に向けます。肩に担ぐ、石突きを地面につける、または刃を胸の高さ以上にしたガード姿勢にします。足元にぶら下げてはいけません頭が弧の先を進みます。柄は身体の前を横切り、腕と同じ垂直面上に置いてはいけません
剣下げた手から斜め上前方に向け、約 +35 度にします。真下に向けると、落としたように見えます刃が先行します。手首を支点にするのではなく、腕全体で弧を描きます
斧、ハンマー頭を上に向けるか、肩に担いで、重心を高く保ちます頭部が重量の中心です。最後に到達し、最も強く当たります
ナックルダスター、ガントレット握るのではなく、装着します。両拳を上げた喧嘩のガード姿勢にします肩ではなく腰を使って打ち出します

小道具は、使い手自身の身体で無理なくできる姿勢で持たせてください。 キャラクターより長いものを片手で持つ場合、腕と同じ面に置くとクリッピングが発生するため、そのように持たせてはいけません。

3. レンダリングして確認する
blender --background <rig>.blend --enable-autoexec --python scripts/anim_render.py -- spec.json out/
ffmpeg -start_number 0 -i "out/side_%03d.png" -vf "scale=240:-1,tile=6x6" sheet.png

カメラはアニメーション全体の範囲に合わせて自動でフレーミングし、視野角から距離を算出するため、何もフレームから外れません。調整できるのはmargin(デフォルトは1.10)だけです。少なくとも2つの角度からレンダリングしてください。右脚でのキックは、左側からでは見えません。

シートはそれ自体ではなく、REFERENCEと照らし合わせて評価してください。 ステップ2aの_intentの文を開き、シートの各フレームをそれと照合します。頭は上がっているか、刃が先行しているか、柄は体の前を通っているか。コンタクトシートで確認できるのは、レンダリング結果が仕様に合っていることだけです。仕様が正しかったかどうかは分かりません。その後のすべての工程では仕様が正しいものとして扱われるため、間違ったポーズを低コストで修正できるのは、ここが最後のポイントです。シートとリファレンスが食い違う場合は、リファレンスを優先して仕様を変更してください。

4. GIFを納品し、そのGIFを確認する
ffmpeg -framerate 30 -start_number 0 -i "out/side_%03d.png" -framerate 30 -start_number 0 -i "out/tq_%03d.png" -filter_complex "[0]scale=420:-1[a];[1]scale=420:-1[b];[a][b]hstack=2,split[s0][s1];[s0]palettegen=stats_mode=diff[p];[s1][p]paletteuse=dither=bayer:bayer_scale=3" -loop 0 anim.gif

シートは、必要なサイズで一度だけ読み込んでください。それより大きくする必要はありません。 コンタクトシートは、この工程で最もコストのかかるオブジェクトです。同じコンテキストで後続のツールを呼び出すたびに画像が再送信されるため、実行の終わりまでに、早い段階でフル解像度のシートを読み込むと数十万トークンを消費します。タイル状に縮小し、特定の部位について確認する場合はその部分を切り抜いてください。また、計測すれば確認できることを再確認するために、シートを開き直さないでください。確認できることを数値で表せる場合――武器が手から離れるか、手足を貫通するか、どの角度になっているか――は数値化し、テキストを1行読むだけで済むようにしてください。

次に、完成したGIFからフレームを取り出して確認してください。動きは静止画とは違って見えます。また、エンコード設定の失敗は表面化しないことがあります。

ffmpeg -i anim.gif -vf "select='not(mod(n,2))',tile=4x3" -vsync 0 verify.png

作成したクリップが、作成していないアニメーションを壊す

RobloxのデフォルトのAnimateスクリプトは、アイドル、歩行、走行、ジャンプ、落下、よじ登りをCore優先度で再生します。作成したアニメーションをIdle以上の優先度で再生すると、そのアニメーションが動かす関節は、再生中ずっとデフォルトのアニメーションをすべて上書きします。

そのため、全身を使ったアイドルループは、武器を持って立っているキャラクターに対する正しい修正ですが、プレイヤーが歩くと脚の動きを止めてしまいます。クリップが歩行サイクルより高い優先度で脚を動かすためです。これはまさに「歩行アニメーションがない」ように見え、アイドルを作成したキャラクターだけに発生するため、そのキャラクターの武器の問題のように見えます。

次のいずれかを選び、どれを選んだか明記してください。

  • アイドルを**Core**優先度で作成し、デフォルトの歩行アニメーションを優先させる。または
  • アイドルでは脚を動かさないようにし、腕と胴体だけを動かして、腰より下はデフォルトの移動アニメーションに任せる。または
  • 移動アニメーション一式も作成する(歩行と走行をMovementで作成する)。持ち方によってキャラクターの歩き方も変える必要がある場合は、これが唯一の選択肢です。

プレイテストで、キャラクターごとに確認してください。 その場に立ち、歩き、走り、ジャンプし、着地します。脚を確認してください。ファイター1人あたり約15秒で済み、これを検出できる静的な確認方法はありません。クリップもリグも正しいのに、2つのクリップを同時に再生している間だけ不具合が発生するからです。

R15 と R6

R15 を推奨します。 R15 には肘と膝があるため、参照画像に示されるあらゆる角度に対応する関節があり、それぞれに FK の制御ボーンを割り当てられます。

.blend ファイルのないカスタムメッシュの R6 リグ(剛体の GLB パーツ + 調査した Motor6D C0/C1)では、scripts/r6_clip.py を使って関節空間で作成します(正確な Motor6D チェーンを通じて実際のパーツをレンダリングし、各キーでルートを接地して、足の y 座標/スタンスの滑り/手足の重なりを報告します)。scripts/r6_luau.py で Luau を出力します(Pose CFrame をそのまま出力し、R15 の仕様にも対応し、フォルダー全体を置き換えます)。変換処理は scripts/r6_joint.py にあります。注意点 39~40 を参照してください。 標準の R6 アバターも同じ方法で動作します(2026-10-22 に実証済み)。CreateHumanoidModelFromDescription(desc, Enum.HumanoidRigType.R6) のダミーの 6 つの Motor6D を調査し(編集モードでも存在します)、チェーンの静止位置を中心とした実際のパーツサイズのボックス型 GLB を作成して、rig.json を書き込みます。Studio で再生したクリップは、接触キーでのレンダリングと 0.00002 studs の誤差で一致しました。

R6 の手足は肘のない剛体の単一ブロックです。腕を折りたたんだボクシングガードは、R6 ではまったく取れないポーズです。これを求めると、腕全体が持ち上がります。ゲームで必要な場合に限って R6 を使用し、ポーズ間の動きが硬くなることを想定してください。これは R6 本来の見た目であり、欠陥ではありません。

Roblox への導入 — パイプライン全体

エンドツーエンドで検証済みで、アップロードは不要です。

# 1. author + preview until it reads right   ("preview": true)
blender --background <rig>.blend --enable-autoexec --python scripts/anim_render.py -- spec.json out/

# 2. generate the Studio builder for one or many specs
python scripts/to_roblox.py kick.json punch.json wave.json > build.lua

2b. Studio の前にエクスポートを検証します: blender --background <rig>.blend --enable-autoexec --python scripts/rbx_axis_check.py -- spec.json --mid。 レンダリングと Roblox の CFrame チェーンの間で、キー設定された各パーツの完全な回転を比較します(落とし穴 35~37)。 to_roblox.py --folder ReplicatedStorage.X.Y --no-verify は、概要を返す yield を含まないビルダーを出力します。spec の markers は KeyframeMarkers になります。

  1. build.lua を execute_luau に貼り付けます。これにより ReplicatedStorage.CustomAnims が作成され、spec ごとに 1 つの KeyframeSequence が格納されます。同じ名前のものは置き換えられ、その後、作成時に指定した再生時間でそれぞれが読み込まれることを検証し、 レポートを出力します。指定した再生時間と異なるものがあれば失敗です。先に進まないでください。

  2. references/studio-binder.lua を StarterPlayer.StarterPlayerScripts 配下の LocalScript にコピーし、BINDS テーブルを編集すると、プレイヤーキャラクター上でキー操作によりアニメーションを再生できるようになります(リスポーン処理にも対応)。オプションでダミーにも同期できます。

エクスポーターが読み取る spec フィールド:rbx_name(Studio での名前)、priority(デフォルトは Action で、標準の歩行/待機アニメーションを上書きします)、loop。

アップロード不要: KeyframeSequenceProvider:RegisterKeyframeSequence(seq) は ContentId を返し、それを Animation.AnimationId に直接割り当てられます。必要なのは Animation 機能だけなので、LocalScript から実行時に呼び出せます。アセットのアップロード、モデレーション、アカウントは不要です。機能するのはプレーンな文字列のみです(hash:// と rbxasset:// はどちらも失敗します)。これらの ID はセッション内でのみ有効です。テストには問題ありませんが、公開するには実際にアップロードしたアセット ID が必要です。scripts/upload_animation.py はこれをヘッドレスで行います(2026-10-08):Studio から KeyframeSequences をダンプし、Rojo で実際の .rbxm を再構築して、Open Cloud の assetType Animation としてアップロードし、完了をポーリングして、各シーケンスに AnimationId 属性を設定する apply_ids.luau を出力します。手動で右クリックして「Save to Roblox」を行うことなく、ロスレス(ポーズ 80/80 件とマーカー)で、キャラクター上で再生できることを検証済みです。

注意すべき点(詳細は落とし穴 29~34):

  • 最新のリグには Motor6D ではなく AnimationConstraint が含まれている場合があります。15 個あっても Motor6D は 0 個という構成もあります。アニメーションは引き続きパーツ名でバインドされ、変更なく再生されます。
  • Enum.PoseEasingStyle に Quad はありません。使用できるのは Linear/Constant/Cubic/Elastic/Bounce です。
  • 編集モードで .Transform に値を書き込んでも、ポーズをプレビューできません。これはアニメーションチャンネルであり、Animator のみが適用します。代わりに、アタッチメントを使った順運動学で軸の対応を検証してください。
  • Studio のツールには見落としがあります。3D ビューポートではなくスクリプトタブを表示している間は capture_screenshot が失敗し、プレイモードの出力にもアクセスできないことがあります。そのため、バインダーのように実行時スクリプトが画面上で自ら診断できるようにしてください。

座標系は異なります。Roblox は +Y が上/−Z が前方、Blender は +Z が上/−Y が前方です。

無料ライブラリを代替として使う

アニメーションの作成が行き詰まった場合、Creator Store には無料の R15 アニメーションがあり、search_asset で見つけられます。無料で、事前にライセンスされており、クォータもアップロードもモデレーションも不要で、すでに Animation アセット ID が付与されています。無人エージェントのルールでは、エージェントが検索して選択することは、人間の介入には当たりません。

コメント