無論是AAA級的主機游戲,還是層出不窮的移動端游戲,角色換裝幾乎都是必不可少的功能,有的甚至是核心功能,像暗黑3和魔獸世界的幻化系統(如圖1)。這個功能沒什么新鮮點。網上關於Unity換裝的文章不勝枚舉,我再添一篇也沒意思,本系列旨在通過換裝功能的實現,來講解一些被Unity引擎所隱藏起來的那些細節。
(圖1:暗黑3和魔獸世界的幻化系統.來源:互聯網)
我剛剛上班的時候就奇怪,同樣都是FBX文件,有的導入到Unity后渲染組件就是MeshRenderer,而有的則是SkinMeshRenderer。記得當初還問過前輩,不過他的回答記不清了,總之我沒有聽懂。不知道大家是不是曾經也有過類似的疑問。Unity是一款很容易上手的引擎,但代價就是隱藏了很多實現細節。如果不能明白背后的原理,那么在做一些功能時總是感覺隔靴搔癢本。本文標題中提到骨骼,蒙皮,動作.我們的整個換裝也正是圍繞這三個核心來展開。先來簡單解釋一下它們。
骨骼
我們在引擎中使用的任何可繪制的物體,也就是mesh,往往是由頂點信息所組成的集合。渲染的過程,也就是利用這些頂點信息,把這些模型繪制出來。如果對於沒有動作的靜態模型,這一切就足夠了。當我們提到模型動畫的時候,無論以何種方式來實現動畫,最本質上都是對模型頂點集合的一系列變換。所以在3dmax中要想制作一個動畫,並不需要一定有骨骼,你可以在關鍵幀中直接修改模型的頂點信息。可以想象,這種方式無疑是低效的,特別是對於復雜的模型的復雜動作。這也就引出了"骨骼+蒙皮"的工作方式。在3DMAX中,有兩種骨骼,分別是Bones和Bip(如圖2).前者的自由度較高,后者則是特殊版的Bones,按照人體的骨骼結構,制定好規范,直接使用。Bones的一般用於場景物件和非脊椎動物的動作,比如披風,旗幟,鳥類,而Bip大多用於脊椎動物,或類人生物的主體部分。本系列中主要以Bip骨骼為例,這是一個典型的父子層次結構。基本符合人體的關節布局和限制。這樣基於骨骼來制作動畫,既直觀又方便。
(圖2:左為Bone,右為Bip.來源:互聯網)
使用Bip還是Bone不是絕對的,對於稍微復雜一點的模型,通常是兩者結合,如下圖中對於初音的骨骼搭建,可以發現身體的主要結構是使用Bip,對於頭發和裙擺處則使用更自由的Bone骨來進行細節化處理。
(圖3:bip+bone結合使用。來源:互聯網)
蒙皮
前面我們提到動畫實際上mesh的頂點在進行運動。單純的骨骼並不會對Mesh頂點的變化有任何影響,而蒙皮的意義就在於把Mesh上的頂點與對應骨骼關聯起來。之后只需要對骨骼進行動畫關鍵幀的制作,就可以帶動模型的頂點產生變化。那骨骼具體是怎么與mesh頂點關聯的呢。模型的骨骼結構中的每個節點都會在整個骨骼架構中中有一個序號,比如(根節點的序號可能為0),然后模型上的每個頂點都記錄它受哪幾根骨骼的影響,以及影響的權重多大(雖然max中沒有對受骨骼影響的數量限制,但一般為了運行效率不會超過三根,如圖4)。
(圖4:蒙皮過程中對頂點對應骨骼的權重修改)
負責角色建模的美術同學,往往會把模型建成雙手向兩側抬起的姿勢,這個姿勢叫作T-pose(也叫綁定姿勢,如圖5)。這樣做是為了方便動作美術進行蒙皮,蒙皮后模型上每個頂點都會保存在綁定姿勢下相對於部分骨骼的相對位置。當對骨骼進行動畫操作時,這些頂點就會實時的根據它所綁定的的各根骨骼的當前位置,及影響的權重,進行空間變換和插值,以計算出新的位置。這個過程展開的話會稍微有一些復雜。感興趣的朋友可以去看《游戲引擎架構》里的詳細講解。
(圖5:綁定姿勢T-pose)
動作
所有蒙皮后Mesh,都應該通過調節骨骼來制作動畫,如我前面說的,因為此時模型上的頂點位置已經是實時通過骨骼位置和權重實時計算出來的了。這也就是為什么對Unity中帶有skinMeshRenderer組件的GameObject進行移動,旋轉等操作,並不會影響模型的最終渲染。而具體在存儲上每一根骨骼都會記錄一個在當前動作幀的情況下,骨骼相對於父節點SQT(縮放,平移,旋轉),也可能是其它數據結構,用來記錄它的姿勢。假定游戲的預期幀率是60FPS,美術設計一個時長1s的行走動畫,也就是在max里你可以看到60幀,但美術並不會一幀一幀的key動作,而只會在幾個關鍵的時間節點上插入關鍵幀,設定好相應的動作。在播放的時候,運行到關鍵幀以外的動畫幀時,各個骨骼數據的位置是通過其兩邊的關鍵幀上的骨骼數據進行插值來的。插值的種類也有很多,我還沒深入研究過,不展開了。但是這種插值過度並不一定讓設計者滿意,就可以進一步添加關鍵幀來解決。
(圖6:在動作條上添加關鍵幀,並在關鍵幀上調整骨骼動作.來源:互聯網) (圖7:動作關鍵幀插值后形成動畫.來源:互聯網)
總結
串起來說一下,角色美術建立好T-pos下的模型后,交給動作美術,動作美術基於模型的姿勢,大小,形態來選擇Bip或者bone骨骼來搭配出相應的骨骼結構。然后進行綁骨,把Mesh上的頂點和對應的骨骼關聯起來。這樣在后面制作動作關鍵幀的時候,骨骼的變化會帶動與其綁定頂點的變化。整個流程,聽起來很簡單,每個環節都有專門的美術負責,原畫,模型,動作.本文是這個系列的前置篇,雖然不懂這些具體的美術流程,也並不影響使用引擎的API來進行換裝的實現。但是不明白這背后的美術流程,乃至更深層的數學原理,便不會變通,做的功能也不夠靈活。
在之后的文章中,我們通過在Unity中實現一個簡單的換裝功能,其中的一些內容也會涉及本文的知識點。