Community寫作與編輯github.com

hmohammed7/roblox-animation

在 Blender 中根據 JSON 姿勢規格,無人值守地創作 Roblox 角色動畫(R15 或 R6),並透過渲染連絡表與 GIF 進行驗證,以及比對參考姿勢。

roblox-animation 是什麼?

此技能提供一個完整的、數據驅動的管道,用於在 Blender 中創建 Roblox 角色動畫(R15 和 R6),無需打開 Blender 的圖形用戶界面。它接受一個 JSON 規格文件,定義隨時間變化的姿勢序列,將其轉換為真實的 Blender 動作(Action),渲染出所有影格並生成連絡表(contact sheet)和 GIF。這個流程經過精心設計,能夠捕捉到其他方法常常遺漏的細微錯誤,例如,當“真實姿勢”動作干擾渲染時、在 FK/IK 模式之間切換時,或者四肢因求解器歧義而出現抖動時。該技能包含詳細的參考資料,用於避開常見陷阱、校準特定綁定(rig)的骨骼方向,以及實現風格化的 Roblox 時機(例如 30 FPS、誇張的動作)。它可在任何支援標準 Markdown 檔案格式的 AI 代理平台(如 Claude Code、Cursor)上使用。該管道的效能經過基準測試,整個流程只需幾秒鐘,優先使用數值探針進行快速偵錯,並強調在將動畫規格應用於最終渲染之前,先根據參考圖像進行視覺驗證的重要性。

相容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/hmohammed7/claude-skills/tree/HEAD/roblox-animation

Installed? Explore more 寫作與編輯 skills: steipete/notion, langchain-ai/langchain, bytedance/podcast-generation · View all 6 →

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

Roblox 動畫,無人值守模式

第一次使用這台機器? 請閱讀此資料夾中的 LOCAL.md。如果該檔案不存在,請執行 roblox-skills-setup 技能(或將 LOCAL.template.md 複製為 LOCAL.md 並填寫內容)。 LOCAL.md 儲存你的路徑與工具位置;它是你專屬的檔案,絕不回傳。

將動畫創作視為數據(一個定義隨時間變化的姿勢的 JSON 規格),將其烘焙到真實的 Blender 動作中,渲染它,然後在相信結果之前先查看結果。

循環是:創作 → 渲染每一影格 → 拼貼成連絡表 → 查看 → 修正 → 重複。 這個技能存在的每一個部分,都是因為這個循環的某個環節捕捉到了其他所有檢查都遺漏的失敗。

先讀這個:最浪費時間的陷阱

大多數 Roblox 綁定出廠時都內建了一個儲存其靜止姿勢的 Blender 動作。 Blender 在渲染期間會重新計算該動作。所以如果你設定了姿勢數值然後渲染:

  • 每個數值探針回報你的姿勢已完美套用
  • 每個渲染的影格顯示的都是綁定的預設姿勢
  • 數據和圖像永遠無法對齊,且沒有任何錯誤訊息

清除該動作也沒有幫助,因為那個動作就是靜止姿勢本身——清除它,四肢就會縮回軀幹。

解決方法:在同一個動作中插入關鍵影格,然後逐影格使用 frame_set() 並進行渲染。如此一來,動畫就是那個動作,沒有任何東西可以覆蓋它,未觸及的骨骼透過常數外插保持其靜止值,而你最終會得到一個真實的動作——這正是 Roblox 匯出所需要的。scripts/anim_render.py 已經實作了這個邏輯。

完整列表在 references/traps.md 中——共有 28 個陷阱。在除錯任何問題之前請先閱讀它。

使用 FK 進行創作,而非 IK

Roblox 的 KeyframeSequence 是一個按關節旋轉的樹狀結構,每個 Motor6D 對應一個。這就是 FK。每個 R15 綁定都為每個關節提供一個控制骨骼來與之匹配。如果你使用 IK 目標來驅動角色,就等於在一個 Roblox 從未要求的求解器中進行來回轉換,並為此付出代價:

  • 僅限位置的 IK 目標會讓肢體的 ROLL 保持自由,因此方塊狀的 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 綁定帶有 ARM_IK_FK / LEG_IK_FK 自訂屬性,預設值為 1.0(IK)。將它們設為 0.0,添加關鍵影格(這樣 frame_set 就無法將其復原),然後在 FK 模式下進行創作。上述的方向慣例是在一個綁定上測量的;calibrate_rig.py 和 sweep_control.py 會在你的綁定上重新測量它們,所以對任何你沒用過的綁定都要執行這兩個腳本。你的綁定的 .blend 檔案路徑需填入 LOCAL.md。

只有在肢體必須命中精確的世界座標點時,才使用 IK。然後請閱讀陷阱 12–15。

讓它看起來像 Roblox,而不是像參考影片

  • 30 FPS,一個戰鬥動作持續 0.3–0.7s。動畫編輯器的預設值就是 30fps。現實生活中的時機對遊戲來說太慢了。從動作的真實運作方式中提取力學機制;從 Roblox 中提取時機。
  • 五個姿勢:待機、預備、接觸、跟隨、收招。
  • 每個片段使用緩動——用 "ease": "in" 加速進入打擊,用 "ease": "out" 平穩結束。固定的平滑步進(smoothstep)會讓每個關鍵影格減速,因此打擊動作會在其自身的接觸影格上緩慢停止,整個動作會感覺軟弱無力。
  • 誇張化。 真實的 Roblox 戰鬥動畫遠遠超過人類的活動範圍,並且必須透過輪廓來辨識。
  • 渲染成純灰色("plain": true)。複雜的虛擬人偶紋理會將方塊狀的綁定格變得難以辨認,最終你會在除錯服裝而不是姿勢。真正的 Roblox 動畫正是因為這個原因而在純色假人上展示。

references/pose-recipes.md 有實際的數值——包含防禦、預備、架勢、接觸和跟隨階段的測量角度表、時機骨架,以及兩個容易出錯的規則(肩膀 + 手肘總和必須保持在約 120 度以下;高踢需要 UpperLeg X 超過 -120 度,否則腿會與軀幹重疊)。從這些數值開始,然後根據預覽畫面進行調整。不要重新推導它們。

要快——用數據說話,而不是憑感覺

整個循環只需幾秒鐘。如果一次處理需要幾分鐘,那就有問題了。在中階電腦上測量,一個 24–36 影格的動畫:

階段時間備註
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 呼叫

一台機器花費在生成一個準備好放入 Studio 的動畫的時間:遠少於一分鐘。 真正耗費時間的是創作疊代,所以要把時間花在預覽上,絕不要花在完整渲染上。有了 references/pose-recipes.md 作為起點,第二個動作應該能在 1–3 次預覽內完成——references/ 中的勾拳和揮手在第一次嘗試時就是對的。

使用 "report": true 會列印每個關節在每個關鍵節拍的位置:當一個姿勢看起來不對勁時,它能在一次執行中命名出有問題的關節,而不是透過五次渲染來猜測。

不要為了回答一個探針就能回答的問題而去渲染。

不可妥協的規則

每一條都存在,因為跳過它曾經讓看起來正常的東西出錯:

  1. 絕不相信一個退出碼為 0 的執行。 anim_render.py 會斷言每個影格的綁定完整性,斷言影格已經寫入,否則會硬性退出並傳回非零值。
  2. 查看影格。 每一次處理都要看。
  3. 如果有參考資料,請建立並排比較並以此為判斷依據——絕不要只看渲染結果。
  4. 檢查完成的 GIF 本身,而不是你用於編碼的 PNG 檔案。
  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 會回報形變骨架與控制骨架、動作陷阱、IK/FK 開關狀態,以及哪些控制實際上會移動東西。 sweep_control.py 會給出每個軸的方向、正負號和可用範圍——它會測量骨骼的方向和位置,因此不會遺漏純旋轉控制。

如果 FK_* 骨骼看起來不起作用,那就是 IK/FK 開關的問題,而不是綁定失效。

2. 創作規格

包含 fps、duration、w、h、margin、views、properties、plain、preview、report 以及 keyframes[](其中包含 {t, ease, bones: {Bone: {rot|loc|target|aim}}})。

幾乎總是使用 rot。對於沒有末端效應器的控制(如 ROOT),使用 loc。target / aim 是 IK 的逃生艙——請參閱陷阱 12–15。

如果你忘記以下三點,每次都會出錯:

  • 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.8s 迴旋踢)和 references/example-fk-punch.json(0.5s 交叉拳),以及 references/pose-recipes.md。

2a. 如果手中有道具,首先研究它是如何被真實握持的。

這個步驟在你創作任何關鍵影格之前就要完成,而且它不是可選的。 一旦一個片段中包含武器或工具,“姿勢看起來對不對”就不再是有關綁定的問題,而是有關那個物體的問題,這是關於世界的事實,而不是可以從矩陣推斷出來的東西。

這個規則存在的目的是為了防止一個真實建構中發生過的失敗:一把長柄刀被創作成刀頭朝下,懸在持有者的臀部。之後的每個下游階段都完美地完成了自己的工作——引擎重現了所創作的握持方式,姿勢條與連絡表影格完全匹配,握持誤差為 0.000,完全沒有武器穿入身體的樣本——結果遊戲發布的是一個頭朝下拿著的長柄武器。在這裡創作的錯誤姿勢,對之後的每一個檢查都是不可見的,因為之後的每一個檢查都是在測量與這個姿勢的一致性。 當人類最終檢查時,裁決是它拿反了。他們是對的,而代價是整個下游階段都要為一個這裡十秒鐘做出的決定買單。

在創作之前:

  1. 搜尋該武器類型是如何被攜帶和使用的。 搜尋練習者的照片,而不是概念藝術,也不是其他遊戲。十秒鐘的閱讀勝過四輪對數值的猜測。
  2. 將答案作為 _intent 寫入規格中,用一句話描述武器:“刀頭朝上,柄越過前導肩膀”、“刀刃從放低的手向上並向前傾斜”。這句話將作為連絡表的判斷標準——見第 4 步。
  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)是唯一的調整參數。至少渲染兩個角度——右腿踢從左邊是看不見的。

然後根據參考資料來判斷連絡表,而不是根據連絡表本身。 打開第 3a 步中的 _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

只看一次連絡表,以你需要的、且尺寸不要更大的方式看。 連絡表是這個管線中最昂貴的物件:一個圖像會在後續每次工具呼叫時在同一上下文中重新傳送,因此在執行初期讀取一個全解析度的連絡表,到執行結束時會浪費數十萬個 token。將它縮小拼貼,當問題涉及特定肢體時裁切到該肢體,並且不要為了重新檢查一個本來可以測量的東西而重新打開它。當檢查可以是數值時——武器是否脫手、是否穿過肢體、以什麼角度放置——就把它做成數值並讀取一行文字。

然後從完成的 GIF 中抽出影格並查看它們——動態與靜態的閱讀感覺不同,而且編碼設定可能默默地失敗:

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

你創作的片段會破壞你沒創作的片段

Roblox 預設的 Animate 腳本以 Core 優先級播放待機、行走、奔跑、跳躍、墜落和攀爬動畫。你所創作並以 Idle 或更高優先級播放的任何動畫,都會在其播放期間遮蓋它對每個關節所設定的姿勢。

因此,一個全身待機循環——讓持武器角色靜止站著的正確解決方案——會在玩家行走時停止腿部移動,因為你的片段以比行走循環更高的優先級對腿部設定了姿勢。這看起來完全就像“行走動畫缺失了”,而且只會出現在你創作了待機動畫的角色身上,這會讓人感覺...

...(後續內容被截斷)

[截斷]

相關技能