為什麼說“角色移動”看上去很簡單,卻需要極高的技術力與細節成本?
“角色移動”是大部分遊戲的玩法基礎。不過在遊戲中,他看起來如此的簡單自然以至於很容易被玩家所忽略掉。實際上,角色的移動涉及到動畫、渲染、物理、同步等多項開發技術以及大量的美術工作。即使單從設計上講,“角色移動”也經常會給開發者們帶來一些讓人陷入兩難的問題。總而言之,想將角色移動做到完美確實是相當困難的。
虛幻5演示的Demo中有一段爬牆的動畫,想做出這種效果其實是非常不容易的
這篇文章會圍繞3D角色的移動,來談談為什麼如此基礎的功能卻需要極高的技術力與細節成本?
一、移動原理與常見問題
之前一篇科普文章中曾講述過“遊戲角色移動的基本原理”。
遊戲世界與真實世界相同,也是一個三維的空間(2D遊戲是二維空間),我們遊戲中的所有角色,都會在這個三維的世界裡面出生、移動、互動直至死亡。除了角色以外,遊戲中的其他物件也是如此產生的,比如說建築、武器、道具等等。他們身上都儲存著自己的座標位置,當我們在移動我們的角色的時,其實就是在不斷的修改當前角色的座標值。
所以想讓一個物件在遊戲世界中動起來其實很簡單——改變他的位置即可。
但假如我們控制的是一個人形的角色,只是簡單的修改他的位置是不夠的,我們還需要讓角色走得更自然和真實。換句話說,就是讓角色的移動看起來更貼近真實世界。這裡面其實涉及到人體結構、物理受力等很多複雜的問題,我們很難通過簡單的數學模型或物理引擎來達到期望的效果。因此,目前遊戲界通常採用人為製作的動畫的方式來取代真實的物理模擬。
動畫的實現有頂點動畫和骨骼動畫兩種方式,現在普遍採用骨骼動畫來處理角色的移動。骨骼動畫,會將3D模型抽象為一些關鍵點的集合,這些關鍵點互相連線成“骨骼”並組成一個完整的骨架結構,我們通過改變骨骼的朝向和位置來既可以為模型生成動畫。
由此可見,一個角色的動作是否自然,很大程度上取決於動畫師的設計。
現在,有了位置以及動畫,角色就可以真正的動起來了。遊戲中每一個角色的移動需要有兩個基本的系統共同維護,一個是角色的動畫系統,另一個是隱藏在程式碼背後的位置計算系統(可以稱為移動元件系統)。角色動畫系統負責按照時間戳播放其動畫,一般由美術通過三維建模軟體製作(2D的比較簡單,就是按幀替換圖片,3D一般是骨骼動畫)。將動畫匯入到遊戲引擎中,就可以看到該角色會不停播放移動的動畫,但是他不會向前產生任何位移。
那麼角色是不是就可以完美的動起來了呢?不,噩夢才剛剛開始。首當其衝出現的就是一個非常常見的基本問題——“滑步”,滑步產生的根本原因是動畫上的表現與其實際位置的移動距離不匹配(角色一步走10米,看起來像是在滑行)。
解決滑步通常從兩個方面考慮:
第一個方面是針對角色常規的移動。一般來說,玩家在走路、跑步的過程中速度是有規律的,要麼是勻速、要麼是勻加速。這時候可以把移動元件系統應用起來,也就是每當玩家播放移動動畫的時候通過玩家的狀態來合理的計算其應該走的位移長度並應用。這種方式就可以實現通常意義上的角色移動了。也就是說,這些比較有規律的移動計算可以交給程式碼層面去處理,程式碼需要仔細考慮角色所處的狀態通過合理的數學模型去模擬計算位移。
第二個方面是針對比較複雜的特殊移動。角色如果不是勻速移動也不是勻加速移動,我們的移動元件系統根本沒法算,就算你程式碼寫的再好也很難達到美術想要的效果。所以我們通常會採用Rootmotion的解決方案,即每一幀的位置交給美術處理,他們在做動畫的時候把位移資訊也寫到動畫裡面,我們移動的時候讀取美術的資料就好了。
當然,考慮到美術工作量等問題,我們不能都用rootmotion解決。角色還有一些特殊處理但是又比較通用的狀態,比如轉彎、轉身、突然停住等,顯然轉彎的時候玩家的身體會傾斜、轉身時候我們的腳步應該逐漸踩過去,突然停住要有一個剎住腳步並恢復的效果(而不是直接滑過去),這些一般我們使用動畫狀態機配合混合空間(Blendspace:可以根據兩個輸入的動畫來進行混合)可以解決大部分問題,不過還是需要美術製作很多動畫資源。
而狀態機,和計算機的FSM(有限狀態機)概念是相似的。在遊戲裡面,其實就是我們預先定義了一些節點作為角色行為狀態,比如跑,站立,下蹲等。當我們按下下蹲按鈕的時候,判斷一下是否滿足某種狀態切換的條件,滿足的話角色將就會從預設狀態轉移到下蹲狀態。
仔細觀察,你會發現很多以前遊戲都沒有處理這些細節,就是因為太過繁瑣。
最近幾年,一個稱為MotionMatch的技術流行開來,用來解決各種動畫的銜接問題。他的基本原理就是首先製作一個豐富的動畫資源庫,然後在角色移動的時候不斷的根據當前角色的動作與狀態資訊根據演算法從資源庫裡面挑選最適合下一幀播放的動畫。育碧的“榮耀戰魂For Honor”就採用了這種技術,同時配合深度學習去挑選動作,達到了非常不錯的效果。不過這項技術對於小的團隊明顯不太適用。也許多年後會出現一套完善的共享開源動作庫,大家都可以體驗到該技術帶來的便捷了。
https://www.gdcvault.com/play/1023280/Motion-Matching-and-The-Road
好了,如果我們成功解決了上面的這些問題,是不是就可以讓角色愉快的移動了呢?
答案當然是NO!下面還有一堆進階的問題等著我們解決,而且不同的遊戲面對情況截然不同!
二、移動進階問題
1.碰撞
一個玩家動起來了,那如果遇到了障礙怎麼辦呢,是推著障礙走還是被阻擋住,這其中的標準如何制定?如果撞到了另一個玩家,可以把人頂走麼?玩家上樓梯是一級一級上還是平滑著上?玩家在多少度的斜坡上可以走呢?類似的問題數不勝數,很多都是遊戲設計上的問題。
這些問題大部分可以在物理引擎的支援下,通過射線檢測等方式解決,但是也有一些不好處理的情況。
對於上面的問題,這裡簡單給出常見的方案。比較大的物件都會設定為靜態的(也就是不會移動的),所以玩家移動時會被擋住,而小的東西玩家可以直接踩過去。至於能否頂走其他玩家,要看遊戲的型別而決定。上樓梯我們為了保持攝像機的平滑,會把臺階的物理設定成平滑的。
2.特殊模式
前面說了那麼多都只是角色行走,而在遊戲中設計者的思路是天馬行空的,策劃可能想讓角色飛起來、游泳、吊單杆、爬梯子、以及各種逼著牛頓從棺材板出來的反物理行為(如多段跳、輕功)等,那麼要如何處理這些移動模式呢?
其實上面的每一種特殊的移動方式,都需要特殊的處理方式,幾乎沒有統一的解決方案。比如爬梯子,為了讓玩家的手能夠與梯子的把手重合,我們需要嚴格設定梯子的每隔的間距,並做到與動畫相適應。同時,也需要做出一種特殊的移動模式,只當角色處於爬梯子狀態時只能勻速的修改座標的Z值。
簡而言之,特殊模式很複雜,每一個功能拎出來一個都夠程式和美術做一陣的。
《尼爾機械紀元》2B爬梯子的過程設計的非常舒適
3.特殊物件
我們控制的角色不一定是人形的角色,還可能是汽車、動物。
對於汽車物件,有一點好處是我們基本不用考慮動畫的適配問題,因為汽車不需要像人一樣揮動四肢,只要輪子動起來就可以了(當然像地平線、極品飛車這種3A級別的賽車遊戲,車身的動畫也是相當複雜的)。但是我們需要在程式裡面比較完美地模擬出其移動的軌跡,這就必須要涉及到物理引擎的使用和優化,難度也是相當之高。
對於動物,我們需要解決一些骨骼的處理問題,由於人形角色在遊戲中使用的比較廣泛,相關的系統支援的都還算不錯。但是由於動物的骨架結構與人不同,所以我們需要製作新的美術資源,這也就意味著人形的骨骼資源不能適配到動物上。如果你做了各種結構迥異的生物,那美術肯定就要被累死了。(所以,仔細觀察的話你會發現,一個遊戲裡面很多小怪角色的身體結構都是相似的)
4.多個移動狀態的銜接
前面提到了角色可能走、跑、唱、跳、飛、遊等,當你從一個狀態切換到另一個狀態時應該如何銜接?走著走著突然被車撞飛(有點慘),是應該頭著地還是屁股著地?是被撞的一瞬間就切換成飛出去的動畫麼?假如你往前翻越一個柵欄的時候被打了一槍,應該往前還是往後倒?翻牆的時候能翻越多高多厚的牆體?
有些時候我們可以通過開啟角色的Ragdoll(布娃娃系統),完全交給物理引擎去處理一些移動模擬。但是很多情況下,我們想要玩家能夠控制最後的效果,所以又不能完全交給物理引擎。目前的部分引擎的動畫系統支援基於物理的動畫,我們可以按照固定權重進行物理和動畫的混合,一定程度上減少了美術的工作量,也可以做到一些更真實的效果。
5.移動同步
前面說了那麼多,還只是針對單機遊戲。如果你是網遊,那麼你的角色動起來的時候應該如何告訴其他客戶端怎麼動?如果延遲過大造成兩個客戶端的位置或者動畫不一樣怎麼辦?在很多遊戲中,移動同步是一個相當大的難題,因為玩家的位置每一幀都可能在變化。
常見的同步方案有“幀同步”(Lockstep)和“狀態同步”,也有很多優化的方案。
6.其他細節
比如關卡這個地方能不能走,不能走怎麼防止玩家過去?(可以採用的空氣牆處理,然而玩家很討厭空氣牆)
能不能兩個人一起走過一個狹小的空間?因為如果一個玩家站在那裡,其他玩家過不去可能體驗會很差,所以可能考慮調整碰撞體大小來讓兩個人可以並排通過。當然,這也涉及到關卡的設計問題。
走了一半穿模怎麼辦?調整動畫或者碰撞體。
類似的問題還有很多很多,我這裡就不再一一列舉了。
三、總結
總的來說,角色移動不是簡單的與某幾個系統有關,可以說他涉及到了整個Gameplay的大部分設計邏輯,甚至在一些遊戲中,我們認為他是遊戲的玩法核心也毫不為過。
然而,很多時候,他顯得那麼自然以至於很多玩家都將其忽略了。
來源:遊戲開發那些事
相關文章
- 為什麼說現在很火的區塊鏈技術“老笨慢”?區塊鏈
- 精讀《為什麼專家不再關心技術細節》
- 我為什麼勸你不要過度糾結於技術細節?
- web前端入門很容易,全棧卻很難,為什麼每個程式設計師都那麼說?Web前端全棧程式設計師
- Python為什麼發展這麼快速?原因很簡單!Python
- 很詳細、很移動的Linux makefile 教程Linux
- 為什麼搞計算機工作的人總是看上去很清閒計算機
- 一個很簡單的查詢,為什麼用不到索引索引
- 為什麼說Objective-C很難學?Object
- 為什麼機器學習會選擇Python語言?很簡單!機器學習Python
- 為什麼越簡單的技術對於開發人員越難
- 誰說 JavaScript 很簡單了?JavaScript
- 大模型時代需要什麼樣的安全水位?火山方舟首度公開「會話無痕」技術細節大模型會話
- 為什麼寫爬蟲用Python語言?原因很簡單!爬蟲Python
- 漫畫:為什麼搞計算機工作的人總是看上去很清閒計算機
- 技術實力的本質是什麼?
- Redis為什麼快及其高可用技術的幾種方案Redis
- 為什麼新來的技術很難接手維護一個系統
- 為什麼單態需要同步
- 簡單的效能測試說明為什麼Go比Java快?GoJava
- 什麼是技術債,為什麼要還技術債?
- 為什麼說K&R是技術寫作的典範
- 一個小的技術細節
- CodePen的CSS技術細節CSS
- 為什麼數字化轉型不僅需要技術,也需要人的改變?
- 【CNN】很詳細的講解什麼以及為什麼是卷積(Convolution)!CNN卷積
- 為什麼說精益方法是數字轉型的核心驅動力?
- 為什麼有的人說技術不重要,有的人說重要?
- 為什麼域名SSL證書的價格這麼高?有哪些成本?
- 為什麼說Java是2021年最值得學的技術?Java
- 為什麼寫技術文章?
- 程式設計師工資高,卻有很多人想轉行,理由很簡單!程式設計師
- 看起來很唬人,然而卻簡單實用的CAP理論
- 為什麼不斷做遷移,那是在還技術債
- 為什麼說雲資料庫是商業的成功、技術的倒退?資料庫
- 為什麼有些公司的IT很亂?
- 對VR來說, 眼球追蹤技術在裡面到底是一個什麼角色?VR
- 為什麼從事雲原生開發需要學習容器技術