1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        為什么說“角色移動(dòng)”看上去很簡(jiǎn)單,卻需要極高的技術(shù)力與細(xì)節(jié)成本?

        共 4430字,需瀏覽 9分鐘

         ·

        2020-11-16 14:30


        “角色移動(dòng)”是大部分游戲的玩法基礎(chǔ)。不過在游戲中,他看起來如此的簡(jiǎn)單自然以至于很容易被玩家所忽略掉。實(shí)際上,角色的移動(dòng)涉及到動(dòng)畫、渲染、物理、同步等多項(xiàng)開發(fā)技術(shù)以及大量的美術(shù)工作。即使單從設(shè)計(jì)上講,“角色移動(dòng)”也經(jīng)常會(huì)給開發(fā)者們帶來一些讓人陷入兩難的問題??偠灾?,想將角色移動(dòng)做到完美確實(shí)是相當(dāng)困難的。

        虛幻5演示的Demo中有一段爬墻的動(dòng)畫,想做出這種效果其實(shí)是非常不容易的

        這篇文章會(huì)圍繞3D角色的移動(dòng),來談?wù)劄槭裁慈绱嘶A(chǔ)的功能卻需要極高的技術(shù)力與細(xì)節(jié)成本?
        1.移動(dòng)原理與常見問

        我之前在公眾號(hào)的一篇科普文章中曾講述過“游戲角色移動(dòng)的基本原理”。

        游戲世界與真實(shí)世界相同,也是一個(gè)三維的空間(2D游戲是二維空間),我們游戲中的所有角色,都會(huì)在這個(gè)三維的世界里面出生、移動(dòng)、交互直至死亡。除了角色以外,游戲中的其他對(duì)象也是如此產(chǎn)生的,比如說建筑、武器、道具等等。他們身上都保存著自己的坐標(biāo)位置,當(dāng)我們?cè)谝苿?dòng)我們的角色的時(shí),其實(shí)就是在不斷的修改當(dāng)前角色的坐標(biāo)值。
        Jerish,公眾號(hào):游戲開發(fā)那些事游戲中的角色是如何“動(dòng)”起來的?

        所以想讓一個(gè)對(duì)象在游戲世界中動(dòng)起來其實(shí)很簡(jiǎn)單——改變他的位置即可


        但假如我們控制的是一個(gè)人形的角色,只是簡(jiǎn)單的修改他的位置是不夠的,我們還需要讓角色走的更自然和真實(shí)。換句話說,就是讓角色的移動(dòng)看起來更貼近真實(shí)世界。這里面其實(shí)涉及到人體結(jié)構(gòu)、物理受力等很多復(fù)雜的問題,我們很難通過簡(jiǎn)單的數(shù)學(xué)模型或物理引擎來達(dá)到期望的效果。因此,目前游戲界通常采用人為制作的動(dòng)畫的方式來取代真實(shí)的物理模擬。


        動(dòng)畫的實(shí)現(xiàn)有頂點(diǎn)動(dòng)畫和骨骼動(dòng)畫兩種方式,現(xiàn)在普遍采用骨骼動(dòng)畫來處理角色的移動(dòng)。骨骼動(dòng)畫,會(huì)將3D模型抽象為一些關(guān)鍵點(diǎn)的集合,這些關(guān)鍵點(diǎn)互相連接成“骨骼”并組成一個(gè)完整的骨架結(jié)構(gòu),我們通過改變骨骼的朝向和位置來既可以為模型生成動(dòng)畫。



        由此可見,一個(gè)角色的動(dòng)作是否自然,很大程度上取決于動(dòng)畫師的設(shè)計(jì)。

        現(xiàn)在,有了位置以及動(dòng)畫,角色就可以真正的動(dòng)起來了。游戲中每一個(gè)角色的移動(dòng)需要有兩個(gè)基本的系統(tǒng)共同維護(hù),一個(gè)是角色的動(dòng)畫系統(tǒng),另一個(gè)是隱藏在代碼背后的位置計(jì)算系統(tǒng)(可以稱為移動(dòng)組件系統(tǒng))。角色動(dòng)畫系統(tǒng)負(fù)責(zé)按照時(shí)間戳播放其動(dòng)畫,一般由美術(shù)通過三維建模軟件制作(2D的比較簡(jiǎn)單,就是按幀替換圖片,3D一般是骨骼動(dòng)畫)。將動(dòng)畫導(dǎo)入到游戲引擎中,就可以看到該角色會(huì)不停播放移動(dòng)的動(dòng)畫,但是他不會(huì)向前產(chǎn)生任何位移。


        那么角色是不是就可以完美的動(dòng)起來了呢?不,噩夢(mèng)才剛剛開始。首當(dāng)其沖出現(xiàn)的就是一個(gè)非常常見的基本問題——“滑步”,滑步產(chǎn)生的根本原因是動(dòng)畫上的表現(xiàn)與其實(shí)際位置的移動(dòng)距離不匹配(角色一步走10米,看起來像是在滑行。

        解決滑步通常從兩個(gè)方面考慮,


        第一個(gè)方面是針對(duì)角色常規(guī)的移動(dòng)。一般來說,玩家在走路、跑步的過程中速度是有規(guī)律的,要么是勻速、要么是勻加速。這時(shí)候可以把移動(dòng)組件系統(tǒng)應(yīng)用起來,也就是每當(dāng)玩家播放移動(dòng)動(dòng)畫的時(shí)候通過玩家的狀態(tài)來合理的計(jì)算其應(yīng)該走的位移長度并應(yīng)用。這種方式就可以實(shí)現(xiàn)通常意義上的角色移動(dòng)了。也就是說,這些比較有規(guī)律的移動(dòng)計(jì)算可以交給代碼層面去處理,代碼需要仔細(xì)考慮角色所處的狀態(tài)通過合理的數(shù)學(xué)模型去模擬計(jì)算位移。


        第二個(gè)方面是針對(duì)比較復(fù)雜的特殊移動(dòng)。角色如果不是勻速移動(dòng)也不是勻加速移動(dòng),我們的移動(dòng)組件系統(tǒng)根本沒法算,就算你代碼寫的再好也很難達(dá)到美術(shù)想要的效果。所以我們通常會(huì)采用Rootmotion的解決方案,即每一幀的位置交給美術(shù)處理,他們?cè)谧鰟?dòng)畫的時(shí)候把位移信息也寫到動(dòng)畫里面,我們移動(dòng)的時(shí)候讀取美術(shù)的數(shù)據(jù)就好了。

        當(dāng)然,考慮到美術(shù)工作量等問題,我們不能都用rootmotion解決。角色還有一些特殊處理但是又比較通用的狀態(tài),比如轉(zhuǎn)彎、轉(zhuǎn)身、突然停住等,顯然轉(zhuǎn)彎的時(shí)候玩家的身體會(huì)傾斜、轉(zhuǎn)身時(shí)候我們的腳步應(yīng)該逐漸踩過去,突然停住要有一個(gè)剎住腳步并恢復(fù)的效果(而不是直接滑過去),這些一般我們使用動(dòng)畫狀態(tài)機(jī)配合混合空間Blendspace:可以根據(jù)兩個(gè)輸入的動(dòng)畫來進(jìn)行混合)可以解決大部分問題,不過還是需要美術(shù)制作很多動(dòng)畫資源。


        狀態(tài)機(jī),和計(jì)算機(jī)的FSM(有限狀態(tài)機(jī))概念是相似的。在游戲里面,其實(shí)就是我們預(yù)先定義了一些節(jié)點(diǎn)作為角色行為狀態(tài),比如跑,站立,下蹲等。當(dāng)我們按下下蹲按鈕的時(shí)候,判斷一下是否滿足某種狀態(tài)切換的條件,滿足的話角色將就會(huì)從默認(rèn)狀態(tài)轉(zhuǎn)移到下蹲狀態(tài)。

        仔細(xì)觀察,你會(huì)發(fā)現(xiàn)很多以前游戲都沒有處理這些細(xì)節(jié),就是因?yàn)樘^繁瑣。

        最近幾年,一個(gè)稱為MotionMatch的技術(shù)流行開來,用來解決各種動(dòng)畫的銜接問題。他的基本原理就是首先制作一個(gè)豐富的動(dòng)畫資源庫,然后在角色移動(dòng)的時(shí)候不斷的根據(jù)當(dāng)前角色的動(dòng)作與狀態(tài)信息根據(jù)算法從資源庫里面挑選最適合下一幀播放的動(dòng)畫。育碧的“榮耀戰(zhàn)魂For Honor”就采用了這種技術(shù),同時(shí)配合深度學(xué)習(xí)去挑選動(dòng)作,達(dá)到了非常不錯(cuò)的效果。不過這項(xiàng)技術(shù)對(duì)于小的團(tuán)隊(duì)明顯不太適用。也許多年后會(huì)出現(xiàn)一套完善的共享開源動(dòng)作庫,大家都可以體驗(yàn)到該技術(shù)帶來的便捷了。

        https://www.gdcvault.com/play/1023280/Motion-Matching-and-The-Road

        好了,如果我們成功解決了上面的這些問題,是不是就可以讓角色愉快的移動(dòng)了呢?


        答案當(dāng)然是NO!下面還有一堆進(jìn)階的問題等著我們解決,而且不同的游戲面對(duì)情況截然不同!

        2.移動(dòng)進(jìn)階問題

        1.碰撞

        一個(gè)玩家動(dòng)起來了,那如果遇到了障礙怎么辦呢,是推著障礙走還是被阻擋住,這其中的標(biāo)準(zhǔn)如何制定?如果撞到了另一個(gè)玩家,可以把人頂走么?玩家上樓梯是一級(jí)一級(jí)上還是平滑著上?玩家在多少度的斜坡上可以走呢?類似的問題數(shù)不勝數(shù),很多都是游戲設(shè)計(jì)上的問題。



        這些問題大部分可以在物理引擎的支持下,通過射線檢測(cè)等方式解決,但是也有一些不好處理的情況。


        對(duì)于上面的問題,這里簡(jiǎn)單給出常見的方案。比較大的物件都會(huì)設(shè)置為靜態(tài)的(也就是不會(huì)移動(dòng)的),所以玩家移動(dòng)時(shí)會(huì)被擋住,而小的東西玩家可以直接踩過去。至于能否頂走其他玩家,要看游戲的類型而決定。上樓梯我們?yōu)榱吮3謹(jǐn)z像機(jī)的平滑,會(huì)把臺(tái)階的物理設(shè)置成平滑的。

        2.特殊模式

        前面說了那么多都只是角色行走,而在游戲中設(shè)計(jì)者的思路是天馬行空的,策劃可能想讓角色飛起來、游泳、吊單桿、爬梯子、以及各種逼著牛頓從棺材板出來的反物理行為(如多段跳、輕功)等,那么要如何處理這些移動(dòng)模式呢?


        其實(shí)上面的每一種特殊的移動(dòng)方式,都需要特殊的處理方式,幾乎沒有統(tǒng)一的解決方案。比如爬梯子,為了讓玩家的手能夠與梯子的把手重合,我們需要嚴(yán)格設(shè)置梯子的每隔的間距,并做到與動(dòng)畫相適應(yīng)。同時(shí),也需要做出一種特殊的移動(dòng)模式,只當(dāng)角色處于爬梯子狀態(tài)時(shí)只能勻速的修改坐標(biāo)的Z值。


        簡(jiǎn)而言之,特殊模式很復(fù)雜,每一個(gè)功能拎出來一個(gè)都?jí)虺绦蚝兔佬g(shù)做一陣的。


        《尼爾機(jī)械紀(jì)元》2B爬梯子的過程設(shè)計(jì)的非常舒適


        3.特殊對(duì)象

        我們控制的角色不一定是人形的角色,還可能是汽車、動(dòng)物。


        對(duì)于汽車對(duì)象,有一點(diǎn)好處是我們基本不用考慮動(dòng)畫的適配問題,因?yàn)槠嚥恍枰袢艘粯訐]動(dòng)四肢,只要輪子動(dòng)起來就可以了(當(dāng)然像地平線、極品飛車這種3A級(jí)別的賽車游戲,車身的動(dòng)畫也是相當(dāng)復(fù)雜的)。但是我們需要在程序里面比較完美地模擬出其移動(dòng)的軌跡,這就必須要涉及到物理引擎的使用和優(yōu)化,難度也是相當(dāng)之高。


        對(duì)于動(dòng)物,我們需要解決一些骨骼的處理問題,由于人形角色在游戲中使用的比較廣泛,相關(guān)的系統(tǒng)支持的都還算不錯(cuò)。但是由于動(dòng)物的骨架結(jié)構(gòu)與人不同,所以我們需要制作新的美術(shù)資源,這也就意味著人形的骨骼資源不能適配到動(dòng)物上。如果你做了各種結(jié)構(gòu)迥異的生物,那美術(shù)肯定就要被累死了。(所以,仔細(xì)觀察的話你會(huì)發(fā)現(xiàn),一個(gè)游戲里面很多小怪角色的身體結(jié)構(gòu)都是相似的)

        4.多個(gè)移動(dòng)狀態(tài)的銜接

        前面提到了角色可能走、跑、唱、跳、飛、游等,當(dāng)你從一個(gè)狀態(tài)切換到另一個(gè)狀態(tài)時(shí)應(yīng)該如何銜接?走著走著突然被車撞飛(有點(diǎn)慘),是應(yīng)該頭著地還是屁股著地?是被撞的一瞬間就切換成飛出去的動(dòng)畫么?假如你往前翻越一個(gè)柵欄的時(shí)候被打了一槍,應(yīng)該往前還是往后倒?翻墻的時(shí)候能翻越多高多厚的墻體?


        有些時(shí)候我們可以通過開啟角色的Ragdoll(布娃娃系統(tǒng)),完全交給物理引擎去處理一些移動(dòng)模擬。但是很多情況下,我們想要玩家能夠控制最后的效果,所以又不能完全交給物理引擎。目前的部分引擎的動(dòng)畫系統(tǒng)支持基于物理的動(dòng)畫,我們可以按照固定權(quán)重進(jìn)行物理和動(dòng)畫的混合,一定程度上減少了美術(shù)的工作量,也可以做到一些更真實(shí)的效果。


        5.移動(dòng)同步

        前面說了那么多,還只是針對(duì)單機(jī)游戲。如果你是網(wǎng)游,那么你的角色動(dòng)起來的時(shí)候應(yīng)該如何告訴其他客戶端怎么動(dòng)?如果延遲過大造成兩個(gè)客戶端的位置或者動(dòng)畫不一樣怎么辦?在很多游戲中,移動(dòng)同步是一個(gè)相當(dāng)大的難題,因?yàn)橥婕业奈恢妹恳粠伎赡茉谧兓?/span>


        常見的同步方案有“幀同步”(Lockstep)和“狀態(tài)同步”,也有很多優(yōu)化的方案,具體的細(xì)節(jié)可以參考我之前的系列文章。


        網(wǎng)絡(luò)同步在游戲歷史中的發(fā)展變化(一)—— 網(wǎng)絡(luò)同步與網(wǎng)絡(luò)架構(gòu)

        網(wǎng)絡(luò)同步在游戲歷史中的發(fā)展變化(二)——?Lockstep與幀同步

        網(wǎng)絡(luò)同步在游戲歷史中的發(fā)展變化(三)——?狀態(tài)同步的發(fā)展歷程與原理(上)

        網(wǎng)絡(luò)同步在游戲歷史中的發(fā)展變化(四)—— 狀態(tài)同步的發(fā)展歷程與基本原理(下)

        6.其他細(xì)節(jié)

        比如關(guān)卡這個(gè)地方能不能走,不能走怎么防止玩家過去?(可以采用的空氣墻處理,然而玩家很討厭空氣墻)


        能不能兩個(gè)人一起走過一個(gè)狹小的空間?因?yàn)?/span>如果一個(gè)玩家站在那里,其他玩家過不去可能體驗(yàn)會(huì)很差,所以可能考慮調(diào)整碰撞體大小來讓兩個(gè)人可以并排通過。當(dāng)然,這也涉及到關(guān)卡的設(shè)計(jì)問題


        走了一半穿模怎么辦?調(diào)整動(dòng)畫或者碰撞體。

        類似的問題還有很多很多,我這里就不再一一列舉了。



        3.總結(jié)



        總的來說,角色移動(dòng)不是簡(jiǎn)單的與某幾個(gè)系統(tǒng)有關(guān),可以說他涉及到了整個(gè)Gameplay的大部分設(shè)計(jì)邏輯,甚至在一些游戲中,我們認(rèn)為他是游戲的玩法核心也毫不為過。


        然而,很多時(shí)候,他顯得那么自然以至于很多玩家都將其忽略了。


        —? ?請(qǐng)幫忙轉(zhuǎn)發(fā)分享、點(diǎn)個(gè)在看吧???—

        游戲開發(fā)那些事


        我是Jerish,網(wǎng)易游戲客戶端開發(fā)工程師,

        這里既有技術(shù)干貨,也有游戲科普,歡迎大家關(guān)注

        回復(fù)"gamebook",獲取游戲開發(fā)書籍

        回復(fù)"C++面試",獲取C++/游戲面試經(jīng)驗(yàn)

        回復(fù)"操作系統(tǒng)",獲取操作系統(tǒng)經(jīng)典書籍

        游戲開發(fā)交流群(875867499)


        往期熱門文章:

        如何學(xué)習(xí)大型項(xiàng)目的源碼?

        史上最全的C++/游戲開發(fā)面試問題總結(jié)

        游戲中的角色是如何“動(dòng)”起來的?



        新開了讀者討論功能,大家可以評(píng)論起來了


        瀏覽 119
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            自拍小说 | 男女交性视频无遮挡全过程 | 国产一级黄色 | 亲子伦视频一区二区三区 | 人妖videosex高潮另类 | 国产一级a爱做片免费观看人与生 | 娇妻被邻居脔到高潮呻吟小说 | 韩国成人在线视频 | 91 国产 爽 黄 在线相亲 | 边摸边做边吃奶 |