布料系統原理淺析和在Unity手遊中的應用
這是侑虎科技第291篇原創文章,感謝作者賈偉昊供稿,歡迎轉發分享,未經作者授權請勿轉載。當然,如果您有任何獨到的見解或者發現也歡迎聯絡我們,一起探討。(QQ群:465082844)
前言
專案技術測試結束之後,各種美術效果提升的需求逐漸成為後續開發的重點,角色效果部分的提升目標之一便是在角色選擇/展示介面為玩家提供更高的品質感,於是可以提供動態效果的布料系統就作為了技術預研的方向。筆者在之前的端遊專案中有較多使用布料系統製作布料效果的經驗,這次也嘗試了在Unity引擎中進行布料效果製作的幾種方法。本文整體框架基於之前整理的一篇關於布料系統基本原理的文章,結合Unity引擎中的製作方法,為需要在手游上有更好的角色動態表現需求的專案提供一些方向和思路。
一、什麼是布料系統
隨著時代的發展和移動裝置硬體效能的提升,物理引擎被越來越多的移動遊戲所使用。物理引擎處理的物件主要可以分為剛體(Rigid Bodies)和柔體(Soft Bodies)兩大部分,剛體主要應用在物理碰撞、破碎、布娃娃等系統中,而柔體最為重要的應用代表就是布料系統。“風吹仙袂飄飄舉,猶似霓裳羽衣舞”,白居易《長恨歌》中描繪的美麗情景就是布料系統所希望實現的遊戲效果之一。筆者著眼於布料系統,從其相對於傳統制作方法的優勢出發,描述其基本的實現原理,以及對常見的幾種帶有布料系統的物理引擎進行簡單的對比,最後以目前在開發的手遊為例,分享使用Unity引擎製作手游上可以應用的角色布料效果的基本方法。
在物理引擎中,通過物理計算來模擬布料效果的系統可以稱之為布料系統。雖然名為布料系統,但並不僅僅用於表現角色衣服的布料效果,而且可以應用於毛髮、墜飾,甚至女性的某些柔軟部位……下面的幾張圖就給出了一些遊戲中應用了布料效果的地方。
《九陰真經》布料效果宣傳圖
《無盡戰區》遊戲中的角色布料效果
《劍網3》重置版中的布料效果截圖
《王者榮耀》中妲己尾巴有部分的布料效果
目前來說,大部分3A級別的主機遊戲中,布料效果已經幾乎是標準配置了,而在國內的端遊中,也已經得到了大範圍地應用。而在手遊中,只看到為數不多的幾款在小範圍地使用,比如只有在角色選擇介面,或者只有主角身上會開啟部分佈料效果。
二、為什麼要使用布料系統
如果把為什麼要使用布料系統這個問題的答案歸結為策劃和美術需求的話,就未免太過膚淺了。在角色身上或者場景的元件中表現布料的效果,比如上面圖中角色的裙襬,場景中迎風招展的旗幟,都可以增加遊戲的真實感,提升美術效果。但基於物理引擎的布料效果的具體優勢還要從與傳統做法的對比說起。傳統的布料效果實現方式非常簡單——美術手動製作的動畫。
在物理引擎被廣泛使用之前,遊戲中的絕大部分動態效果都是通過固定的動畫來表現。這個做法非常容易理解——角色身上的飄帶也好,頭髮也好,在動畫師的眼中,與角色的手腳四肢沒有任何區別,新增骨骼,進行蒙皮,製作動畫,無論一幀一幀自己手K還是用Max的柔體效果外掛生成,都可以製作出逼真的布料執行的效果。(在更早的使用網格動畫的年代,原理也相差不多。)如果你覺得效果不夠好?那簡單,再多加一些控制骨骼,多給美術一些時間,就可以做出更好的效果。
基於動畫的製作方法雖然可以滿足大部分的需求,但隨著時代的發展,無論玩家還是遊戲開發者都在追求更好更真實的效果,這種製作方式表現出來的布料效果的缺點慢慢顯現出來:
1. 布料效果不夠真實
預先製作的動畫是一份確定的資料,無論在什麼情況下只要播放這段動畫表現出來的效果都是完全一樣的。這種穩定性在某些情況下並不是一種真實的表現,比如一個很簡單的例子是角色的原地轉身,通常情況下這種轉身是由程式改變模型朝向來實現了,動作依然是Idel這樣的動作,本來柔軟的布料應該表現出應有的慣性,但動畫系統很難做出相應的表現。 另外,雖然在單個的動畫中,布料的表現效果足夠好,但是在各個動作之間轉換,甚至多個動作融合到一起進行表現的時候,用於表現布料效果的骨骼融合結果就會不那麼自然,真實感也就大打折扣。
除此之外,當你靈巧地躲過一個敵人的箭矢,感受到敵人箭矢從耳邊呼嘯而過的驚險與刺激的時候,箭矢所產生的風如果可以吹起你的衣服是否更帶感呢?傳統的動畫效果也幾乎無法實現這樣的需求。
2. 無法應對越來越多的變化
越來越多的遊戲提供給玩家一個沙盒的世界,也就意味著玩家可以控制角色做出越來越多遊戲設計者不可控制不被預期的行為和動作表現。在這種情況下,基於骨骼動畫的布料表現就有些力不從心。比如當角色有移動速度的變化時,我們通常可以通過改變動畫的播放速度提供對應的表現,但是移動速度很快和移動速度很慢時,裙襬頭髮的飄揚效果都是完全一樣的,甚至當玩家面對一堵牆按下移動按鈕,角色開始播放跑步動畫,雖然並沒有移動,但仍然可以看到角色的裙襬和頭髮在迎風飄揚……
3. 限制時裝的設計和製作
目前大部分遊戲在設計角色的時候由於要考慮到角色未來可能會出的時裝,可能採用最大化骨骼的製作方案。所謂最大化骨骼,就是在角色製作初期就確定好角色最多可能有哪些骨骼,在之後製作角色時裝的時候,要完全在最初定義的最大化骨骼範圍內。如果超出了這個範圍,就需要修改所有時裝的模型以及角色的所有動作,並全部重新匯出,這種修改的代價是非常大的。
角色的模型與最大化骨骼的設計
這些預留的最大化骨骼,有很多是在角色預設設計的時裝中沒有被使用的,但是為了給未來預留更多的可能,因此需要留好控制裙襬、長髮等部件的各種最大化骨骼,而且注意,這些骨骼上都需要製作對應的動畫效果,或者在未來製作某套需要這一骨骼的時裝的時候,把所有的動畫新增上對應骨骼的動作,重新匯出。在美術工作量、美術資源的大小、遊戲的執行效率等方面,這種做法都有一定的負面影響。
當然,大部分引擎都已經支援了子模型的方式,也就是引擎可以把一些子模型動態地合併到一套骨架上。但是《劍靈》的製作人員提供了另外一種思路——主角的動畫只製作身體主要部位的動畫效果,對於所有的裙襬、墜飾這樣的物體,都統一使用布料系統來製作。這一製作方案可以完美解決設計角色時裝時要考慮是否有骨骼可以驅動的問題,從而解放美術的想象力,節省美術的冗餘工作,執行時的效率也得到一定的提升。
劍靈中角色的效果
4. 無法支援動畫重定向之後的動作
動畫重定向是一種常用的動畫複用技術,可以讓一個模型A使用另外一個模型B的動畫資料,但是如果模型A帶有裙襬、長髮這樣的額外部分,而模型B的動畫中並沒有驅動對應網格的骨骼,那麼重定向之後的裙襬就會非常僵硬——大多數情況下它們以T-pos的姿勢跟隨父骨骼進行整體的移動。
很多格鬥遊戲在受擊效果中會大量使用了動畫重定向技術,要麼讓動畫模板包含所有可能的骨骼資訊,要麼讓那些不被驅動的面片就呆在那裡不動。前者幾乎無法實現的,因為對於非CS骨骼來說,不同的骨骼名稱在不同的模型中對應的部分可能是不同的,比如Bone001在A角色中對應驅動頭髮部分的動畫效果,而在B影響中驅動了裙襬,即使強制要求美術按照統一的規則進行命名,這個工作量和出錯的概率也是非常大的,那就需要一套包含所有角色最大化骨骼的“最大化最大化骨骼”。而後者可能是策劃與美術無法接受的。
總之,基於物理模型的布料系統提供一套在遊戲執行時根據環境計算布料效果的解決方案,這一系統可以有效地彌補傳統動畫製作方式的上述這些不足,為遊戲提供具有更強真實感的布料效果。
三、布料系統的實現原理
在應用布料系統之前,我們先淺顯地看一下布料系統的發展過程和基本原理。
在圖形學領域開始布料模擬的研究可以最早追溯到上世紀八十年代,最早的時候學術界對於布料系統的研究肯定不是用於布料的實時計算,而是離線渲染,甚至只是為了生成一副靜態的圖。比如Terzopoulos在1987年的論文提出一種方法,將布料當作矩形的網格,然後使用半隱式整合的方式來更新它的位置,使用彈性理論來模擬動畫效果。Breen在1994年提出了一個新的視角,即基於粒子(Particle-based)的方案,使用用於模擬纖維織物的Kawabata measuring system來模擬布料的執行效果。Baraff和Witkin在1998年發表的論文中提出了一種在保證布料模擬效果穩定的前提下允許更大時間步長的方案,這一方案也被逐漸地改進為更快的方法。在這之後,基於AABB樹等資料結構的演算法優化,與剛體的碰撞,布料自身的碰撞計算等問題逐漸被研究和提出相應的解決方案,布料模擬也逐漸從一個學術界的研究方向發展成為可以應用於影視製作的工業技術,進而應用於需要實時計算的遊戲領域。下面的幾幅圖給出了幾個重要的論文在當年所展示的布料模擬效果。
Breen在1994年製作的布料效果
Baraff和Witkin在1998年使用大時間步長模擬的布料效果
Bridson在2005年考慮了與剛體碰撞的布料效果
布料模擬技術大致由布料建模、數值計算、碰撞處理和渲染顯示四大部分組成。從前文可以看出,在30多年的研究發展中,各國的研究人員針對這些技術提出了多種不同的方法,在這其中,布料建模是最為重要的部分,因為它影響甚至決定了後面的數值計算和碰撞處理的實現機制。被提出以及在應用的建模方法有很多種,比如較早的懸鏈線性模型、純集合變換的布料變形模擬方法,基於物理的彈性變形模型,粒子系統模型等等,甚至也有基於紋理生成幾何褶皺的方法。而現代遊戲引擎中實現和整合的模型通常是基於物理方法的質點-彈簧模型(Mass-Spring Model),這一方案具有模型簡單且運算效率較高的特點,我們著重講述一下這一模型的基本原理。
在質點-彈簧模型中,布料被當做網格上的粒子來進行模擬,這些粒子之間由彈簧減震器進行連線。每一個彈簧連線兩個粒子,並且基於粒子的位置和速度來產生作用力。粒子可以受重力影響,彈簧可以設定為不同的型別,比如拉伸彈簧(stretch springs)、剪下彈簧(Shear Springs)和彎曲彈簧(bend springs)等。
質點彈簧模型結構示意圖
作用力的計算過程主要包括兩部分,一個是質點所受的重力:
另外一個彈簧對於質點的作用力,我們使用Ks來表示彈簧本身的約束力,Kd表示阻尼因子,l0表示彈簧的靜息長度,那麼根據物理原理得到作用力的計算方程如下:
當我們計算出這一模型中的所有作用力之後,就可以根據牛頓第二定律計算每個粒子的加速度:
an是粒子n的加速度,fn是作用於粒子n的作用力,mn是粒子n的質量。當我們計算好加速度之後,我們可以用它來模擬一個很小的時間步長內的速度和位置變化:
這就是最簡單的質點彈簧模型的基本原理。其他更多的改進方案,更多的效果支援,都是基於這一簡單的物理模型來實現的。通過修改質點的質量引數,彈簧的型別以及阻尼因子、靜息長度等引數,就可以實現絲綢、麻布,甚至竹蓆等不同的布料效果。當然,要實現一套真正可用的完整模型和可以支援執行時計算的高效模擬演算法,還需要很多問題和細節要去解決,這些在本文中就不再進行贅述,有興趣的同學可以參考Cloth Simulation相關論文或者閱讀開源引擎相關原始碼。
四、遊戲中成熟的布料系統引擎
在瞭解了布料系統實現的基本原理之後,我們來看一下常用的幾款提供了布料系統實現的引擎。其實對於布料系統,甚至物理系統來說,很多引擎都不會自己去實現,而是整合已經提供了相應功能的中介軟體。世界三大物理引擎有AMD公司的Bullet、Nvidia家的PhysX,還有現在被Microsoft從Intel手中收購了的Havok,他們都提供了整套的布料模擬解決方案供其他引擎整合和使用。
Bullet作為一個跨平臺的開源物理引擎,當然支援布料模型的建立和模擬,但似乎沒太聽聞哪些遊戲大作使用了這一引擎製作布料效果然後大肆宣傳,因此在遊戲行業內的應用不如另外兩款多。由於筆者對這一引擎瞭解不多,在此不進行詳細的介紹。這款引擎的一大好處在於開源,想了解布料系統實現細節的同學可以直接翻看原始碼來進行閱讀和學習。
Bullet引擎展示的布料效果
PhysX提供了功能強大的布料系統,Unity中的物理引擎部分就是基於PhysX搭建的,Unreal引擎同樣預設集成了PhysX,筆者猜想這是受英偉達自由許可政策的影響——“PhysX 二進位制軟體開發包可免費用於非商業和商業遊戲與應用程式(這意味著,沒有許可費或特許使用費)”。除了一些使用Unreal引擎的主機大作基於PhysX製作布料效果,國內騰訊公司的《天涯明月刀》中武俠風的布料效果也是基於PhysX來製作的,他們也以此作為一個賣點進行推廣。
《天涯明月刀》中使用PhysX製作的布料效果截圖
在PhysX引擎中,除了布料的模擬和碰撞之外,已經支援了布料的破碎(Cloth Tearing)效果。這種效果要求當模型中的彈簧被拉伸得長度超出一定限度之後,可以破壞掉原來的模型結構。
PhysX中布料的破碎效果
Havok也是一款被廣泛應用的物理中介軟體,很多3A大作的各種物理效果都是基於它進行的製作。Havok提供了Max和Maya等多種建模工具的外掛來製作並匯出布料資訊,執行時通過物理計算實現質點彈簧模型的更新過程。下圖是Havok 2015版本的Demo視訊中的效果圖,雖然還不支援破碎等效果,但是在碰撞檢測的精度、執行效率等方面有了不小的改進。
Havok Demo中的布料效果演示
五、Unity中的布料製作和應用
筆者之前所經歷的端遊專案中使用的是Havok作為物理引擎來製作的布料效果。Havok引擎提供了一套非常豐富而又複雜的工具鏈來支援布料製作功能,當時為美術翻譯、編寫的使用方法就有幾十頁,美術甚至需要通過組織沙龍來分享布料效果的製作方法和經驗。下圖列出了Havok中布料製作的幾個核心概念和它們之間的關係。
Havok中布料建模的核心概念
這裡面Simulation Cloth,以及Buffer都可以被看做承載粒子和彈簧資料的容器,Collidable是用於碰撞的膠囊體,布料屬性通過一系列Operator來進行設定,多個Operator組成一個State,多個State又可以重複執行以多次模擬計算的方式獲取更好的布料效果。為了避免布料穿插或者提升碰撞檢測的效率,Havok又提供了Local Range Constraints、Bone Global Plane Constraints等多種約束來在正常的模擬之外限定布料粒子可以運動的範圍,比如Local Range Constraints就以半徑、最小距離和最大距離這三個引數指定了粒子可以運動的空間範圍。
可見Havok中對於布料系統的設計和實現是如此的複雜。因此,在查閱Unity中布料製作方法的時候我以為會有大量的資料和內容需要學習,結果官方文件中的Cloth部分只有幾螢幕內容,而其除了用於處理碰撞之外的核心元件只有Cloth Component一個,並且整個製作過程是在Unity Editor內部的,著實讓我有點意外。在學習具體制作方法之前,還是老思路,先對Unity豐富的外掛進行一下調研。
5.1 外掛調研
需要提前說明的是,前文所描述的布料系統及其原理,主要是針對在主機和端游上使用的物理模型的布料效果,它們基於網格頂點,可以做到非常精細的效果。其實還有一種製作布料效果的方法——基於骨骼進行物理模擬。這種方法的原理更加簡單,把骨骼當做一個個通過關節連線在一起的鉸鏈,給予一定的物理引數,來模擬動畫之外的動態效果,而最終效果是通過蒙皮反應到模型網格上的。由於骨骼數量通常都比頂點數量少很多,因此這種方法具有更高的執行效率,在手遊中使用得也比較多,前面對於《王者榮耀》中妲己的辮子截圖,筆者猜想就是使用的類似的方法。
沿著這兩個不同的思路,筆者查看了幾個相關的外掛:
a. 基於骨骼的方案。基於骨骼的方案在Unity的AssetStore上有多個實現,原理都差不多:Dynamic Bone、Swing Bone、PhysicsBone。
b. 基於質子-彈簧模型的方案。主要看了兩個,一個是官方的Cloth Component,一個是Obi Cloth。
5.2 製作方法
基於骨骼的布料方案中,筆者購買了Dynamic Bone這個外掛進行測試和學習;基於質子-彈簧模型的方案中,筆者選擇了官方原生的Cloth Component來進行測試和對比。
方法比較簡單,新建一個工程,選擇一個專案中使用的角色,分別使用這種方式進行布料效果的製作,然後進行效果和效率對比。
Dynamic Bone提供了一個名為“Dynamic Bone”的指令碼元件來實現骨骼鏈的物理模擬,每一條要模擬的骨骼鏈都需要新增一個動態骨骼的元件,元件中定義了骨骼鏈的根節點和阻尼、彈性、剛度係數、惰性、重力等等引數。元件截圖如下:
Dynamic Bone元件
Dynamic Bone外掛的使用比較簡單,進行一定的配置之後,角色的飄帶等就可以在角色移動、播放動畫、旋轉等情況下有了一些慣性感的動態效果。這裡列舉幾點具體使用時的小Tips:
-
骨骼鏈不能通過Optimize Game Object進行優化。這個要求很容易理解,如果在C#層無法取得骨骼對應的GameObject,自然無法對其進行修改。
-
整個Dynamic Bone元件必須放置在Animator所在的外層才能正常起作用,也就是需要在Animator所在的GameObject的父節點上新增Dynamic Bone元件才可以。由於我們之前Animator是在角色模型GameObject的最外層的,因此這個需求需要對之前的角色模型結構進行一點小的修改。
-
最終效果依賴於骨骼鏈的數量。我們對於飄帶等使用的骨骼進行了非常強的限制,通常只有1-2根,因此結果也可想而知,飄動時有比較明顯的折角現象。
-
必須單獨繫結骨骼的面片才可以做出動態效果。我們有些飾品和短的飄帶繫結到了角色的脊柱等核心骨骼上面,這些骨骼是不能被用來做動態骨骼的,否則角色真個身體就扭曲掉了……
Unity官方所帶的Cloth元件使用稍微複雜一點,但是也不太難,基本步驟包括:
(1)在Mesh Renderer所在的GameObject上新增Cloth元件;
(2)點選Edit Constraints按鈕在彈出的Cloth Constraints介面中編輯Mesh頂點上的常量,比如最大距離、表面滲透。也可以通過筆刷來刷出漸變的值。
(3)在Cloth元件中設定引數和碰撞來提升效果。
Unity Cloth元件
具體制作的細節流程這裡不詳述了,提供一個Youtube上的教學視訊,有比較詳細的過程——《GAME ASSET TUTORIAL - How to Create a Cloth in Unity 5 (PART 2/2)》。
Cloth元件的效果因為是基於網格的,因此不需要繫結骨骼也可以做出動態的效果,而且飄動的單元是mesh頂點,因此效果也比較細膩。(我們的角色面數也比較省,當然做不到像端遊那麼精細的效果。)
5.3 方案對比
在前面的製作過程中已經就這兩種方案的一些方面進行了簡單對比,這裡主要是針對性能進行一些對比工作。首先是在電腦上通過Profiler進行檢視,Demo中有10個Unity Cloth和10個Dynamic Bone製作的角色布料效果,由於遊戲還未正式上線,因此Demo就不截圖了,只給出Profiler的截圖:
效能對比
可以看出,即使是在PC上,基於物理的Unity Cloth元件佔用消耗也是比較大的,有0.28ms的消耗,當然Dynamic Bone也“不甘示弱”,兩個Update加在一起也有0.21ms。在手機上,使用同樣的Demo進行測試,筆者使用了三年前的魅族MX4 PRO進行測試,Unity Cloth會從60幀的滿幀降低到大約30幀左右,而開啟Dynamic Bone只從60幀降低到50+幀,可以看到在手機上的效能消耗還有較大差別,算下來在這臺裝置上基於物理的Unity Cloth比Dynamic Bone要多消耗10ms左右。
需要說明的是,這裡的對比只是一個大概的感性對比,首先我們只會將布料效果應用在選人介面或者角色瀏覽介面中,而且低配會關閉掉,因此效能上的差異不會作為一個非常重要的考量點,另外基於物理的Cloth元件為了方便製作,筆者並沒有把布料的部分單獨拆出來,因此整個模型都作為布料粒子來模擬,只是大部分的頂點的Max Distance設定為0。這應該會對記憶體的佔用和效能消耗有一定的影響。
針對目前專案中角色的製作方法和規範,筆者整理了一下兩種方案的對比情況如下表:
方案對比表
這裡提一個Tips,Unity的Cloth筆者在電腦上測試發現,如果只Deactive Cloth元件或者整個GameObject並不能讓PhysX部分的消耗消失,看上去是隻能減少一些,需要把角色的GameObject從場景中刪除掉才可以。並不確定這是否是一個Unity的bug,從某種程度上這樣做也可以理解——畢竟物理效果是需要連續性的,即使模型並不在渲染,也需要進行一些物理模擬來保證模型被啟用的時候的正確性。
5.4 方案選擇
最終的方案選擇還要再和美術一起驗證下效果再做決定,從目前來看,鑑於計劃只在非常特定的場合下使用,而且我們角色的骨骼數量實在有限,新增骨骼的成本也比較高,Unity的Cloth可能會是我們最終的選擇。
六、總結
本文講述了基於物理模擬的布料系統的實現原理和應用方法,也記錄了最近在Unity中引入布料效果所做的一些工作,希望可以給可能會用到的讀者一些幫助,也希望有經驗的讀者提供一些建議和分享。
最後想借著布料效果這一主題分享一些額外的感受。對比筆者曾經熟悉的Havok引擎,Unity引擎的Cloth元件提供了非常簡單實用的封裝。筆者在學習和整理Havok中的布料系統的製作方法的時候,需要在3DS Max中進行網格的拆分、Buffer的建立、約束和狀態的配置和通道引數的設定等等步驟,才可以在最終的遊戲中看到效果,而引數的修改和結果預覽也是相對麻煩的事情。當然與複雜對應的就是豐富的效果,幾乎任何遊戲中需要的柔體效果都可以進行實現,從武器長鞭到羞羞的乳搖,從柔軟的絲綢到彈彈的果凍,只要工具用得足夠熟練,概念理解得足夠清晰,美術可以製作乃至創造出各種想象不到的效果。而Unity中的Cloth元件,只提供十幾個引數和一個簡單的常量筆刷,相對於Havok可謂簡陋至極,但也能實現六七成的布料效果,對於美術上手來說非常簡便,整個流程大都可以在Editor中進行,而更好更復雜的效果交給外掛開發者來實現。這兩種引擎設計理念完全不同,一個大而全,一個小而精,也許前者更強大,但對於入門者來說,後者更好用。我想,這也是Unity引擎可以有這麼大範圍應用的原因之一吧。
文末,感謝賈偉昊的分享,如果您有任何獨到的見解或者發現也歡迎聯絡我們,一起探討。(QQ群:465082844)。
也歡迎大家來積極參與U Sparkle開發者計劃,簡稱"US",代表你和我,代表UWA和開發者在一起!