Live2D / VRM 角色動畫
這個 skill 來自一個同時支援 Live2D 和 VRM 角色的桌寵(見文末「來源與維護」)。用過的模型有官方範例、VTube Studio 用的模型、VRChat 轉來的 VRM。下面的做法都試過、量過,或者使用者看過、改過。
三條貫穿兩種角色的原則
- 程式層和動作片段會互相蓋。 每幀先算誰、後寫誰,決定了使用者看到什麼。幾乎所有「閃一下」「手放下了」「頭不動」都出在這裡:
- Live2D:程式疊加的值放在
beforeModelUpdate 裡,進不了物理,頭髮、身體不跟著動。要包住 physics.evaluate,在物理之前疊加。
- VRM:three.js 的
AnimationMixer 一幀裡混出來的值和上一幀一樣時,不往骨頭上寫。每幀先由程式擺的站姿、呼吸,會從片段「停住」的那段裡露出來。要跳過正在播的片段寫著的骨頭(按 clip.tracks 的節點名)。暫停時也一樣,要停掉程式重寫站姿。
- 不改動作檔案,在後面加一層程式。 手 K、AI 做的動作往往只動幾根骨頭(揮手只動手臂),像木偶。在片段之後加一層程式算的「帶動」(肩膀跟著抬、軀幹讓、手腕落後、頭晚半拍),片段自己寫了的骨頭不疊。一次做好,所有動作都受益,還能開關對比。
- 驗證靠逐幀記數,不靠看。 動畫的問題只有一兩幀,肉眼很難確認修好了沒有。逐幀記下那根骨頭(參數)畫上去時的值(在 render 之後,或 Live2D 的
beforeModelUpdate 裡讀),修之前、修之後各記一遍對比;再在兩個不同的模型上截圖看。
什麼時候讀哪裡
| 要做的事 | 讀 |
|---|
| Live2D:載入、寫參數、物理、待機、動作、定住、表情 | references/live2d.md |
| VRM:程式姿勢和片段、帶動層、動捕片段、表情、彈簧骨骼、透明視窗 | references/vrm.md |
| VRM:動作配表情、手型和手腕、手碰身上的 IK、打斷不掉手、腿的上限、眼睛跟頭、關鍵幀插值和分段 | references/vrm.md 第 19–31 條 |
| 讓 AI 生成或修改表情、動作 | references/ai-motion.md |
| 跟著音樂點頭、說話時頭動 | references/live2d.md 第 16 條、references/vrm.md「跟節拍」 |
最常見的坑(先查這幾條)
| 現象 | 原因 | 改法 |
|---|
| Live2D 報「Could not find Cubism runtime」或畫不出來 | 載入順序錯了 | Cubism Core → 註冊 render pipe 的模組 → PixiJS Application.init() → 模型 |
| Live2D 寫參數讀出 58、null 這種怪值 | 直接傳了字串 ID | 先 internalModel.getIdSafe(name) 換成句柄 |
| Live2D 頭不跟著動(VTube Studio 模型) | ParamAngle* 是物理的輸出,寫了被蓋掉 | 讀 physics3.json,改寫到它的輸入參數 |
| Live2D 只有頭在晃,頭髮、身體不動 | 疊加放在物理之後 | 包住 physics.evaluate,在它之前加 |
| Live2D 站著一動不動 | VTube Studio 模型沒有像樣的 Idle | 程式待機:頭、身體三個慢正弦 + 呼吸,只寫標準參數 |
Live2D stopAllMotions 後又自己動起來 | 引擎發現沒動作就再播 Idle | 把 motionManager.groups.idle 指到不存在的組,再停 breath |
| VRM 手 K 動作停住的那段手放下、首尾閃一下 | mixer 不寫沒變的值,程式站姿露出來 | 程式姿勢跳過片段寫著的骨頭 |
| VRM 一次性動作結束時一幀跳回 | clampWhenFinished=false 時 mixer 在 finished 之前就關了 action | clampWhenFinished = true,再 fadeOut |
| VRM 動捕動作站得很寬、開頭挪一下、裙子甩起來 | 片段自帶胯和腿 | 轉換時刪掉胯、腿的軌道,只用上半身 |
| VRM 裙子穿進大腿,碰撞輔助線只看到一兩個球 | 碰撞體沒登記進彈簧鏈的碰撞組(three-vrm 只認登記了的) | 按標準骨骼給胯下面的鏈補腿的膠囊;胯別一幀跳過去(references/vrm.md 第 15 條) |
| VRM 片段裡寫的表情看不到 | 每幀的狀態表情、眨眼、口型蓋掉了 | 片段只寫骨頭 |
| 表情在小尺寸下看不出來 | 表情檔案只改了一小塊 | 每個情緒再疊一層參數(瞇眼、臉紅、歪頭、嘴角) |
| VRM 做動作時臉上沒表情 | 表情只跟著狀態走,動作沒帶 | 動作旁邊寫 mood + beats,按動作權重混進去(references/vrm.md 第 25 條) |
| 動作要閉眼、張嘴,模型自己的「睏」「笑」擋住了 | 表情的 overrideBlink / overrideMouth 是 block | 那一下把這些表情壓下去(第 26 條) |
| VRM 單眼眨看不到 | blinkLeft/blinkRight 沒綁形態鍵 | 兩隻眼一起瞇代替(第 27 條) |
| VRM 一個動作打斷另一個,手掉下去再抬起來 | 新動作從站姿開始,交叉淡入經過站姿 | 從新動作裡最像現在的那一刻開始 + 從打斷那一刻過渡(第 19 條) |
| VRM 動捕手指直板或攥拳;手 K 動作手指一直半握 | 重定向的手指 / 動作不寫手指 | 去掉動捕手指,動作裡寫手型(第 22、23 條) |
| 托腮、捂嘴、比心換個身材就落不到地方 | 只寫角度 | 按骨頭和網格現算目標,兩節 IK(第 24 條) |
| 跳舞結束腳一幀跳回去 | 腿 IK 在淡出開始就當幀接管 | IK 按帶腿動作的權重慢慢接過來(第 20 條) |
| 膝蓋半蹲、放鬆的腿彎太多 | 幾層胯的偏移疊在一起 | 膝蓋上限,二分縮胯;抬腳跟反而多彎(第 21 條) |
| VRM 眼睛一直死盯著鏡頭 | lookAt 對著鏡頭,轉頭時眼睛反著轉 | 動作轉頭時視線跟頭、轉頭眨眼、小眼動(第 28 條) |
| 手 K 動作一頓一頓的、不連貫 | 每段關鍵幀都兩頭慢,每個關鍵幀速度為 0 | 單調三次樣條 + 各節關鍵幀錯開(第 29 條) |
| 伸懶腰、舉手手臂直直從兩邊掃上去 / 往兩邊平伸 | 沒有收拳、前臂摺起這些段;扭轉和抬臂沒分開 | 分段重做,扭轉只在門框那一下(第 30 條) |
| 閒置換重心時上半身整個歪向一邊 | 膝蓋上限縮了胯的歪,腰胸還按完整的反著轉 | 胯少歪的部分加到腰上(第 31 條) |
來源與維護
- 來源: Cirra(AI 桌寵,RedCarpG/cirra-deskpet),2026-10 至 2026-11。
- Live2D 程式碼:
src/pet/live2d.ts、src/pet/live2d-physics.ts、src/pet/cubism-core.ts;渲染函式庫 untitled-pixi-live2d-engine 1.4.0(PixiJS 8)。
- VRM 程式碼:
src/pet/vrm.ts、src/pet/vrm-motion.ts,2026-11-11 起還有 vrm-face.ts、vrm-hands.ts、vrm-blend.ts、vrm-reach.ts、vrm-gaze.ts;提交 2b6ab57(clampWhenFinished)、e5e8687(不用 combineSkeletons)。
- 文件:
docs/stage5.md、docs/live2d-motions.md、docs/live2d-common-motions.md、docs/live2d-studio.md、docs/loop-motions.md、docs/expression-outfit-split.md、docs/music.md、docs/vrm.md、docs/vrm-motion.md、docs/vrm-motion-library.md、docs/vrm-studio.md、docs/vrm-toon.md、docs/beat-tracking.md、docs/vrm-skirt.md、docs/vrm-motion-polish.md。
- 經驗:私人 repo 的
lessons/live2d-motion.md、lessons/threejs-vrm-animation.md。
- 源頭: RedCarpG/redcarpg-skills 的
skills/live2d-vrm-animation/。~/.claude/skills/ 裡的是安裝出來的副本,不要直接改。Cirra 裡的程式碼是它的來源,兩邊不會自動同步。
- 怎麼改:
- 在 redcarpg-skills 裡改,走 PR;
manifest.json 版本加一,node scripts/validate.mjs 通過後發版(tag live2d-vrm-animation-v<版本>),再重裝本機副本。先看上面兩個 lessons 檔案有沒有新條目可以收進來。
- three.js、three-vrm、Live2D 渲染函式庫升級後,「最常見的坑」那張表裡和函式庫內部行為有關的幾條(mixer 不寫沒變的值、
clampWhenFinished、shouldRequestIdleMotion、載入順序)要重新確認。
- 只在一個模型上看到的現象,標明是哪類模型,不要寫成通用規律。
- 更新記錄:
- 2026-11-12 · 1.0.0,搬進 redcarpg-skills 公開發布。改掉本機絕對路徑,來源專案寫成連結;內容不變。
- 2026-11-10 · Cirra · 初版:三條原則、坑速查表;Live2D、VRM、AI 生成動作三篇參考;
evals/ 裡兩個測試提示。
- 2026-11-10 · Cirra · 改 VRM 第 15 條(裙子穿模):原來寫的「改成膠囊就好了」沒起作用,換成碰撞組登記、通用腿膠囊、胯跳三條(
docs/vrm-skirt.md);坑速查表加一行。
- 2026-11-10 · Cirra · 第 15 條加長髮進袖子(手臂膠囊不能往回收)、衣服頂出來是蒙皮問題。
- 2026-11-10 · Cirra · references/vrm.md 加「VRM 0.x 的正規化骨骼面朝 -Z」(程式姿勢換朝向、轉身別抵掉 rotateVRM0;提交 e2e6c0c,
src/pet/vrm-basis.ts)。
- 2026-11-11 · Cirra · references/vrm.md 加第 19–28 條(打斷不掉手、帶腿片段淡出時 IK 接管、膝蓋上限和抬腳跟、動捕手指換手型、手型和手腕、手碰身上的 IK、動作配表情、override 擋 beats、空的單眼眨、眼睛跟頭),第 11 條改成指向第 25 條;ai-motion.md 加 face、hands、reach 的格式和校驗;坑速查表加 9 行。來源:
docs/vrm-motion-polish.md §10、§11,src/pet/vrm-face.ts、vrm-hands.ts、vrm-blend.ts、vrm-reach.ts、vrm-gaze.ts、vrm-clip-extras.ts、vrm-pose.ts,sidecar/src/shared/motion-face.ts、motion-hands.ts(合併提交 b2f115d、ea3be9e)。
- 2026-11-11 · Cirra · references/vrm.md 加第 29–31 條(關鍵幀每段兩頭慢導致一頓一頓 → 單調三次樣條和錯開關鍵幀;伸懶腰的分段和上臂扭轉;膝蓋上限縮胯的歪導致上半身斜),坑速查表加 3 行。來源:
docs/vrm-motion-polish.md §12,src/vrm-studio/motion-spec.ts 的 smoothAt、src/pet/vrm-pose.ts(合併提交 c5b4728)。
- 2026-11-11 · Cirra · references/live2d.md 第 21 條加 VTube Studio 模型的兩類排除(物理輸入、不帶 Param 的臉部參數),不然臉部表情遇到點頭就讓開。來源:
src/pet/clash.ts 的 standardInputs、isStandardParam,docs/expression-clash.md(提交 7721742)。