R15) は何をしますか?
あなたは、小さな JSON モーション仕様として動作を作成します。これは、解剖学的な用語 (「右上腕を90度前方に」、「膝を60度曲げる」) で書かれた少数のキーポーズで構成されます。バンドルされたエンジンが、手動ではエラーが発生しやすいすべての処理 (両方のリグの Roblox ジョイント計算、補間、足の接地、3Dプレビューアー、健全性警告、ベイクされたキーフレームエクスポート) を実行します。
ユーザーは結果を視覚的に評価するため、ループは次のようになります: フェーズの計画 → 仕様の作成 → ビルド → 自分でストーリーボードを確認 → 修正 → プレビューとキーフレームの納品。 確認のステップをスキップしないでください。紙の上では正しく見えるポーズ番号でも、実際には明らかに間違っていることがよくあります (腕が胸を貫通する、ボールに届かないキックなど)。
ワークフロー
- 動作を確定する。 リグ (R6 または R15; 本当に推測できない場合のみ質問し、それ以外は R15 をデフォルトとしてその旨を伝える)、利き手、ループまたはワンショット、おおよその時間、および必要なゲームプレイフック (ヒットフレーム、ボールリリース、足音) を確認します。明確なリクエストがあれば、すぐに構築を開始します。
- 数字を書く前にフェーズに分割する。 ほぼすべてのアクションは次のようになります: レディ → 予備動作 → アクション → フォロースルー → 回復。対象のジャンル (戦闘、スポーツ、移動ループ、アクロバット、R6 固有の詳細) については
references/motion-cookbook.mdを参照してください。タイミングテーブルとポーズのレシピがあります。 - 仕様を
<name>.jsonに書く。 ゼロから始めるのではなく、examples/内の最も近いファイルから始めます。 - ビルド:
node <skill>/scripts/ranim.cjs <name>.json --out out(複数の仕様を渡すことができ、1つのプレビューでタブになります)。Node のみが必要で、パッケージは不要です。 - 標準出力に出力されるレポートを読む。 各キーでの頭、手、足の実際の位置 (stud 単位: R = キャラクターの右方向、U = 床からの高さ、F = 前方) がリストされ、
WARN行が出力されます。位置を使用して意図を確認します: 拳は本当に胸の前にあるか、足はボールの高さにあるか。 out/storyboard-<Name>.pngを Read ツールで確認する (すべてのキーを斜め45度からのビューと側面ビューで表示)。 PNG が生成されなかった場合は、ヘッドレスブラウザでout/preview.htmlのスクリーンショットを撮るか、SVG を読み取ります。各パネルを意図したフェーズと比較します。- ポーズが明確に読み取れ、警告がなくなるか、意図的に受け入れられるまで修正して再ビルドする。 2~3回のラウンドが通常です。
- 納品: インタラクティブな
out/preview.html(アーティファクトとして公開するかファイルを送信)、およびout/<Name>.rbxmxとout/<Name>.luaを納品します。可能であればストーリーボード画像をインラインで表示します。Studio に取り込む方法 (後述) と、存在するアニメーションイベントについて簡単にユーザーに伝えます。
モーション仕様
{
"name": "JabCross", // KeyframeSequence の名前とファイル名になります
"title": "Jab-cross combo", // プレビューアーに表示されます
"rig": "R15", // "R15" または "R6"
"priority": "Action", // Idle | Movement | Action | Action2..4 | Core
"loop": false,
"description": "プレビューの横に表示される1~2文。",
"keys": [
{ "t": 0, "label": "guard", "note": "フェーズリストに表示されます。",
"pose": { "UpperTorso": { "turnR": 10, "bendFwd": 8 },
"LeftUpperArm": { "fwd": 50, "out": 8 }, "LeftLowerArm": { "bend": 120 },
"LeftFoot": "flat" } },
{ "t": 0.1, "label": "jab", "ease": "out", "copy": "guard",
"pose": { "LeftUpperArm": { "fwd": 86, "in": 22 }, "LeftLowerArm": { "bend": 6 } } },
{ "t": 0.8, "label": "recover", "copy": "guard" }
],
"markers": [ { "t": 0.1, "name": "Hit", "value": "jab" } ],
"props": [ { "type": "ball", "radius": 0.6, "color": "#e07a2c", "keys": [ ... ] } ]
}
(コメントは説明用です。ファイルはプレーンな JSON である必要があります。)
オプションのトップレベルフィールド: fps (デフォルト30、非常に速い動きには60を使用)、duration (デフォルトは最後のキー)、grounding (高さを手動で制御する場合は "off")、mirror: true (クリップ全体を左右反転、例: 左足用バージョン)、endKeyframe: true。
キー
t秒 (フレームにスナップされます)。最初のキーは 0 です。poseはジョイント名 → チャンネルを 度 単位でマッピングします。キーから除外されたジョイントは、そのキーを通じて単に補間されるため、中間のキーでは関係するジョイントのみを指定できます。一度も言及されなかったジョイントは休止位置 (0°) を保ち、エクスポートされません。キー0以降で最初に言及されたジョイントは、休止位置 (0°) から開始します。copy: 以前のキーのラベルまたはインデックス。ポーズはコピーとして開始され、poseがその一部を上書きします。copyと共に"mirror": trueを使用すると左右が入れ替わります。これは、歩行/走行サイクルを半歩から作成する方法です。easeはこのキー から のセグメントの形状を決定します:smooth(デフォルト、オーバーシュートなしで自然にイーズ)、linear、in(低速で始まり高速で終わる: 一撃を放つ前のため)、out(高速で始まり落ち着く: 衝撃)、inOut、hold、overshoot、anticipate、bounce、elastic。lift: このキーでの、体の最低点の床からの高さ (stud 単位、デフォルト 0)。これがジャンプを作成する方法です。「接地」を参照してください。
ジョイントとチャンネル
角度は解剖学的であり、同じ単語は体の両側で同じ意味を持つため、ミラーリングされたポーズに符号の変更は必要ありません。各チャンネルには逆方向のエイリアスがあります。読みやすい方を使用してください。
| ジョイント | チャンネル (逆方向のエイリアス) |
|---|---|
ルート: LowerTorso (R15)、Torso (R6) | bendFwd (bendBack)、turnL (turnR)、leanR (leanL)、moveFwd (moveBack)、moveR (moveL)、moveUp (moveDown) (stud 単位) |
背骨: UpperTorso、Head | bendFwd (bendBack)、turnL (turnR)、leanR (leanL) |
上肢: Left/RightUpperArm、Left/RightUpperLeg; R6 Left Arm、Right Arm、Left Leg、Right Leg | fwd (back) は手足を前方/上方に振り、out (in) は体から遠ざける/交差させる方向、twistOut (twistIn) は自身の長軸周りに回転させる |
Left/RightLowerArm、Left/RightLowerLeg | bend: 肘と膝を自然な方向に曲げます (0 = 真っ直ぐ) |
Left/RightHand、Left/RightFoot | fwd (back)、out (in)、twistOut (twistIn)。足は文字列 "flat" も受け入れます |
ランドマーク: 腕の fwd: 90 は真っ直ぐ前方を指し、fwd: 180 は真っ直ぐ上を指し、out: 90 は T ポーズです。脚の fwd: 90 は腰の高さの前蹴りです。回転は親から子へと合成されるため、胸の回転は腕も連れて行きます。Head を反対方向に回転させて、視線をターゲットに保ちます。
R6 には6つのパーツがあり、肘、膝、手、足がないため、シルエットは胴体と手足全体の角度から決まります。少し誇張してください。R6 の手足の名前にはスペースが含まれます ("Right Arm")。
接地
デフォルトでは、エンジンはすべてのフレームでルートを上下に移動させ、体の最低点が床から正確に lift stud の高さになるようにします。結果:
- しゃがみ、ランジ、開脚は自動的に腰を下げます。立位のポーズで腰の高さを手動で調整する必要はありません。
- R15 の足に
"flat"を使用すると、足首が解決され、脚がどのような状態でも足裏が平らになります。接地しているすべての足にこれを使用します。空中またはつま先立ちの足には、明示的な角度 ("back": 40= つま先を伸ばす) を指定します。 - ジャンプは、空中のキーでの
liftの値です (離陸時は小さく、頂点で最大、着地時は 0)。空中での体の回転はルートに適用します: バックフリップは、ルートのbendBackがキー間で 0 から 360 に変化します (角度は連続しているため、360 は「0 に戻る」ではなく完全な回転を意味します)。 - 接地がオンの間、ルートの
moveUpは無視されます。床が無関係な水泳や登りなどの場合にのみ、"grounding": "off"を設定します。 - ゲーム内のジャンプとダッシュは通常、アニメーションではなくキャラクターコントローラーによって移動します。ゲームプレイのジャンプ 中 に再生されることを意図したアニメーションの場合は、ボディをポーズし、
liftを 0 のままにします。自己完結型のエモート、ホップを伴う攻撃、宙返りにはliftとmoveFwdを使用します。クリップの終了位置が開始位置と異なる場合、レポートは警告を出します。これは、トラックが停止したときに Roblox がボディを元の位置にスナップバックするためです。
マーカーとプロップ
markersはKeyframeMarkerになり、ゲーム内でtrack:GetMarkerReachedSignal("Hit")を使用して読み取られます。ゲームプレイに関係するすべてのフレーム (ヒットウィンドウ、ボールコンタクトまたはリリース、足音、サウンドキュー) に配置します。propsは プレビュー専用 (エクスポートされません) であり、動作が相互作用する対象に対して判断できるように存在します。type: "ball"とradius、またはsize: [x, y, z]を持つボックス用の他のタイプ (剣は長くて細いボックス)。atは、パーツ名 (プロップはそのパーツに従います。offset: [right, up, fwd]はパーツ自身の軸)、またはキャラクターの下の床点からの固定点[right, up, fwd](stud 単位) のいずれかです。複数のkeysを使用すると、プロップはアンカー間を移動します。arcはそのキーから出るセグメントに放物線状の上昇を追加します (シュートまたはパス)。examples/jump_shot.jsonとexamples/soccer_kick.jsonを参照してください。
良い状態の基準
- 読み取り可能なシルエット。 ストーリーボードでは、各キーがそのシルエットだけで認識可能である必要があります。隣接する2つのキーが似ている場合、そのうちの1つは機能していません。
- タイミングのコントラスト。 ゆっくりとした予備動作、非常に速いアクション (2~4フレーム)、フォロースルーでの短いホールド、ゆっくりとした回復。キー間の間隔が均等であることは、動作が軽く感じられる最も一般的な理由です。
- 全身が参加する。 パワーは足と腰から始まり、次に胸、肩、そして手または足へと伝わります。予備動作では腰と胸にカウンター回転を与え、遠い方の腕で近い方の腕のバランスをとります。
- 足は固定されたまま。 接地している足は、レポート内の R と F の数値をキー間で一定に保ちます。動かす必要がある場合は、その間のキーで持ち上げます (ステップ)。
- 警告がゼロ、 または保持する各警告に理由があること。制限は自然な関節可動域です。制限を超えることは、通常、別のチャンネルが意図されていたことを意味します。
Roblox Studio への取り込み方
ユーザーに両方の方法とイベント名を伝えます。
- コマンドバー (最速): エクスプローラーでリグを選択し、表示 → コマンドバー を開き、
<Name>.luaの内容全体を貼り付け、Enter キーを押します。KeyframeSequence がリグのAnimSaves(または何も選択されていない場合は ServerStorage) に表示され、アニメーションエディターで読み込んで調整できます。 - ファイル:
<Name>.rbxmxを Studio のビューポートにドラッグするか、サービスを右クリック → ファイルから挿入 を選択します。 - 公開: ライブゲームで再生するには、アップロードする必要があります。アニメーションエディターで開いて公開するか、KeyframeSequence を右クリック → Roblox に保存 し、結果のアセット ID を
AnimationオブジェクトとAnimator:LoadAnimationで使用します。Studio での簡単なローカルテストには、game:GetService("KeyframeSequenceProvider"):RegisterKeyframeSequence(seq)を使用すると一時的な ID が返されます。Studio のメニューは頻繁に変更されるため、手順がユーザーの表示と一致しない場合は、その旨を伝え、固執するのではなく現在の表現を調べてください。
エクスポートはベイクされています: フレームごとに1つのキーフレームと線形イージング。そのため、Studio はプレビューで表示されたものをそのタイプの任意のリグで正確に再生します。仕様でアニメーション化されたジョイントのみが書き込まれるため、上半身のみのアニメーションでは、デフォルトの歩行のために脚が解放されたままになります。R15 の出力には AuthoredHipHeight が含まれているため、他のプロポーションのアバターにリターゲットできます。
ファイル
scripts/ranim.cjs— エンジン、プレビューアー、エクスポーターを1つのファイルにまとめたもの。モジュールとしても使用可能:const R = require('.../ranim.cjs'); const c = R.compile(spec); R.report(c); R.sample(c, t)。scripts/selftest.cjs— ジョイント計算を Roblox の Motor6D 公式と照合します。エンジンを編集した後に実行します。examples/—soccer_kick、jump_shot(ボールプロップを使用したスポーツ)、jab_cross(R15 戦闘)、r6_sword_slash(武器を使用した R6 戦闘)、backflip(全身回転とジャンプ)、r6_run(ミラーリングループ)。references/motion-cookbook.md— ジャンル別のタイミングテーブルとポーズレシピ。作成する前に関連セクションを読んでください。