製作剪影角色動畫
由零件骨架構成的角色配方:身體、頭部、兩段式手臂,以及在頭部畫布上繪製的臉部覆蓋層(嘴形與眨眼)。它們會在建構步驟中嵌入 montagent 的循環;如果尚未載入 montagent,請先載入。若要製作角色說台詞的短片,請在規劃前先開啟 角色短片結構。
骨架必須提供的資訊
在開始任何操作之前,請先閱讀骨架的描述。你需要每個零件的:圖片、尺寸、樞紐點(零件旋轉的關節,在原始繪圖中是一個點)、父零件,以及零件繪製的順序(從後到前)。你還需要一個從語音視素 ID 到嘴形的對照表。每個零件的圖片必須經過內邊距處理,使其樞紐點恰好位於畫布的中心。臉部覆蓋層與頭部共用相同的畫布和樞紐點。
如果需求只提供單張繪圖,沒有零件或樞紐點,你無法盲目切割骨架。請告知使用者,並要求提供預先切割好的骨架。
烘焙骨架
Montagent 沒有親代關係,且元素無法更改其圖片。因此,角色會被「烘焙」:捆綁的腳本會根據每個繪製畫面的父零件,計算出每個零件在螢幕上的位置和旋轉角度,並將每個嘴形和眨眼寫成各自的元素,在各自的時間範圍內顯示,並套用頭部的變換。請勿自行撰寫此腳本。
python3 scripts/bake_rig.py <project> <rig> <spec> 會輸出一個專案,其中每個零件都新增了一個對應的軌道。使用 --help 參數運行它以查看規格說明:角色站立位置、指定的姿勢、姿勢之間的移動、搖擺、跳躍、語音及其視素檔案,以及眨眼。每次修改規格檔後,都需再次運行此腳本。它只會取代它自己寫入的軌道。請將規格檔與專案放在一起:它就是角色的真正源頭。
閱讀它的報告。 報告中會列出:它合併的每個嘴形時間段、每個子零件與其父零件在所有繪製畫面上的最大間距,以及需要檢查的瞬間:每個移動的到達時刻和每個關節的極限角度。位置是整數像素,因此最多約 1.5 像素的間距屬於四捨五入誤差,會被圓形關節隱藏。更大的間距表示骨架的樞紐點有誤。
validate 會在角色保持的每個姿勢上報告 R-EASE-INERT,並在嘴形和眨眼軌道的時間段之間報告 N-TRACK-GAP。兩者都是預期的(請參閱問題排除指南)。
烘焙結果看起來像這樣:每個零件都以其樞紐點為中心,並且僅在其移動的位置設有關鍵影格;每個嘴形或眨眼元素則在各自的時間範圍內複製頭部的變換。
{
"frame": {"width": 640, "height": 360}, "fps": 30, "background": "#2E3440", "duration": 2000, "output": "out/baked.mp4",
"tracks": [
{"name": "set", "layer": 0, "elements": [
{"id": "set", "type": "image", "start": 0, "end": 2000, "source": "media/still.png", "x": 0, "y": 0, "origin": "top-left", "width": 640, "height": 360, "fit": "literal"}
]},
{"name": "puppet-torso", "layer": 10, "elements": [
{"id": "puppet-torso", "type": "image", "start": 0, "end": 2000, "source": "rig/parts/torso.png", "x": 320, "y": 330, "origin": "center", "fit": "literal", "width": 80, "height": 280}
]},
{"name": "puppet-head", "layer": 12, "elements": [
{"id": "puppet-head", "type": "image", "start": 0, "end": 2000, "source": "rig/parts/head.png", "x": 320, "y": 190, "origin": "center", "fit": "literal", "width": 90, "height": 160, "rotation": [{"t": 0, "v": 0}, {"t": 500, "v": 6.0, "ease": "linear"}, {"t": 1000, "v": 0.0, "ease": "linear"}]}
]},
{"name": "puppet-mouth", "layer": 13, "elements": [
{"id": "puppet-mouth-0", "type": "image", "start": 400, "end": 700, "source": "rig/parts/mouth_open.png", "x": 320, "y": 190, "origin": "center", "fit": "literal", "width": 24, "height": 60, "rotation": [{"t": 400, "v": 4.8}, {"t": 500, "v": 6.0, "ease": "linear"}, {"t": 666, "v": 4.0, "ease": "linear"}]}
]}
]
}
配方
每個配方提供的都是初始範圍,而非最終答案。每個配方都以一個檢查步驟結束:載入 montagent-craft,然後在繼續之前查看步驟指定的位置。
角度以度為單位,從繪製的靜止姿勢開始計算,每個角度都相對於其父零件,順時針在螢幕上為正。因此,在觀看者右側的手臂以負角度抬起,而在觀看者左側的手臂以正角度抬起。
讓角色站在場景中
- 背景: 一個全影格的場景圖片,設定
origin為top-left,位於 (0, 0),尺寸與影格相同,放在最低的圖層上。請明確設定origin。 - 腳踏實地: 骨架的根部(身體,以腳為樞紐點)應位於地板與牆壁陰影線交匯處,或稍微前面一點。在高度 1080 的場景中,地板的頂部邊緣通常位於畫面下方 80–85% 的位置,因此請將腳放在該位置下方 5–10% 處。
- 尺寸: 角色高度為影格高度的 55–75%,由規格中的縮放比例(影格像素 / 繪圖像素)設定。請測量可見的角色,而非經內邊距處理的繪圖:繪圖高度乘以縮放比例會高估尺寸。
- 位置: 偏向與其道具或卡片相反的一側,約在畫面三分之一處,除非角色獨自站立。
- 檢查:
frame在一個靜止的時刻,檢查腳是否確實踩在地板上,沒有浮空或陷入地面,並且頭部距離影格頂部至少還有 5% 的空間。
入場:跳進來
- 跳躍: 2–3 次,每次 300–450 毫秒,越跳越低:第一次跳躍高度為角色高度的 8–12%,最後一次為 4–6%。水平移動範圍相同,使用
ease-out,因此最後一次跳躍會輕柔著陸。 - 姿勢: 跳躍時手臂放下。在一個繪製的影格上著陸,並在第一次手勢前保持 150–300 毫秒。
- 時間: 在語音開始前完成,至少留出 200 毫秒的間隔。
- 檢查: 在入場過程中執行
frame --from --to --keyframes。檢查腳是否在每個著陸點觸及地板,並且沒有零件落後或超前於身體。
手勢
手勢是一個指定的姿勢,以及進入和離開該姿勢的移動。為每個移動設定一個準備時間(規格中的 in),以便姿勢在開始移動前保持住。
- 手臂放下: 從手臂向外伸出的靜止姿勢開始,將每個上臂向身體方向轉動 40–55°,前臂再轉動 5–15°。
- 揮手: 上臂從靜止位置向外側抬高 40–50°,前臂再向上抬高 25–35°。前臂以肘部為軸心,向兩側擺動 15–20°,週期為 350–450 毫秒,至少擺動 2 個完整週期(800 毫秒或更長)。如果抬得更高,在擺動的內側極限處,手會跑到頭部後面:頭部會覆蓋在手臂之上。
- 指向某物: 上臂近乎水平地指向目標(從手臂向外伸出的靜止位置向上 10–25°),前臂與伸直方向相差 20° 以內,使手指向目標的最近邊緣。在說出該物體名稱的那個詞之前的 1–3 個影格到達。
- 歡呼: 雙臂上臂向上抬高 40–50°,前臂再向上抬高 20–30°。如果彎曲得更多,在動作 overshoot 的最高點,手會藏在頭部後面。
- 移動: 在 250–400 毫秒內完成。使用 overshoot 貝茲曲線
[0.34, 1.56, 0.64, 1]到達,並使用ease-in-out返回靜止姿勢。為了表現跟隨動作,在上臂移動之後的 2–4 個影格,加入第二個僅命名前臂的移動。 - 絕不靜止: 頭部在強調的單詞上傾斜 2–5°,作為一個短暫的擺動或一個 250–400 毫秒的來回移動。如果一個角色保持一個姿勢超過 1.5 秒且沒有任何動作,看起來會像靜止畫面。
- 檢查: 對於每個手勢,在烘焙報告中列出的該關節極限位置處執行
frame --at。檢查手是否與頭部和影格邊緣保持距離,並且在沒有聲音的情況下,姿勢也能被辨識為該手勢。然後在最高舉的姿勢下,以真實比例在肩膀和肘部處執行frame --crop,檢查是否有間距或鬆脫的零件。
根據視素表進行語音同步
烘焙過程會根據語音的視素檔案產生嘴形。每個視素 ID 透過骨架的對照表映射到一個嘴形,而靜音時則使用鳥喙或嘴唇的靜止狀態,不套用覆蓋層。在規格中指定語音元素和視素檔案的名稱。嘴形隨後會跟隨該元素的起始時間和來源範圍,因此移動語音並重新烘焙即可保持同步。
- 最短形狀: 2 個影格。烘焙會將更短的形狀合併到前一個形狀中,並報告每次合併。在 6 秒的台詞中出現十幾次合併是正常的。
- 提前量: 0 毫秒。如果在觀看重播時覺得嘴形慢了,則提前一個影格(在 30 fps 下為 33 毫秒),切勿超過。
- 時間: 探查語音檔案。當其長度與視素檔案聲明的持續時間不一致時,以探查結果為準。
- 檢查: 在三個口說詞語的中間位置執行
query --at,檢查每個位置是否都有一個嘴形元素處於開啟狀態。然後在最長停頓的中間和台詞結束後執行query --at,檢查是否沒有嘴形元素處於開啟狀態。
眨眼
- 長度: 3 個影格(在 30 fps 下為 100 毫秒),最多 4 個。
- 節奏: 每 2–4 秒一次,不規律,絕不在節拍上。在一個大動作著陸後放入一次眨眼,在台詞停頓時放入一次。在任何 8 秒內至少 2 次。
- 避免: 避免在眨眼與手勢到達發生在同一影格,這會掩蓋到達的動作。
- 檢查: 在一次眨眼的中間影格處執行
frame --at,檢查閉上的眼睛是否恰好位於頭部上,並與頭部的傾斜角度一致。