? 久久精品国产一级,W尤物久久99国产综合精品
聯(lián)系我們

給我們留言

聯(lián)系我們

地址:福建省晉江市青陽(yáng)街道洪山路國(guó)際工業(yè)設(shè)計(jì)園納金網(wǎng)

郵箱:info@narkii.com

電話:0595-82682267

(周一到周五, 周六周日休息)

當(dāng)前位置:主頁(yè) > 3D教程 > 圖文教程

Unreal Engine 4 動(dòng)畫系統(tǒng)介紹

來(lái)源: 納金網(wǎng) | 責(zé)任編輯:傳說的落葉 | 發(fā)布時(shí)間: 2019-05-15 08:37 | 瀏覽量:

       Unreal Open Day 2017 活動(dòng)上 Epic Games 資深開發(fā)者支持工程師王禰先生為到場(chǎng)的開發(fā)者介紹了在 Unreal Engine 4 中動(dòng)畫系統(tǒng),以下是演講實(shí)錄。 

 

       大家好!鑒于引擎移動(dòng)端功能以及 UI 優(yōu)化都有同事做了介紹,今天我選擇講的主題是關(guān)于動(dòng)畫。動(dòng)畫是一個(gè)非常復(fù)雜的系統(tǒng),我會(huì)主要介紹一些基本的概念,大家在了解了基本概念后,就可以在上面做出擴(kuò)展。我并不會(huì)教大家怎么使用動(dòng)畫工具,關(guān)于一些動(dòng)畫節(jié)點(diǎn)的使用,我們的在線文檔上都有比較詳細(xì)的說明,也有比較多的資源。今天不會(huì)講到的內(nèi)容包括 Morph target,IK,Retargeting,Rootmotion,Additive,Skeletal Control 這些。

 

       首先,我們先來(lái)看看引擎中的動(dòng)畫系統(tǒng)是如何工作的。為什么我要先講解這樣一個(gè)問題,因?yàn)閲?guó)內(nèi)有很多用戶在使用動(dòng)畫系統(tǒng)的時(shí)候,有很多疑問。這些疑問并不是因?yàn)樗麄儧]有查閱文檔,而是因?yàn)闆]有理解系統(tǒng)的工作方式。本質(zhì)上,動(dòng)畫系統(tǒng)工作原理是非常簡(jiǎn)單的,我這里還是重新介紹一下。

 

112520umwph25ail3ew5k1


我們先來(lái)看看在引擎中動(dòng)畫相關(guān)的資源主要分為哪幾類。

 

       第一大類是最基本的數(shù)據(jù)資源。其中主要來(lái)自于外部 DCC 工具制作并導(dǎo)入的原始資源,我們稱之為 Anim sequence。

 

       然后,有些資源可能為了制作和導(dǎo)入的方便是分散開來(lái)的,但是有些情況下會(huì)組合到一起使用。所以引擎中有一種資源叫 Anim Composite。他是使用多個(gè) Anim sequence 或是自身(Anim Composite)所組合成的資源。在使用時(shí),依然被看作是普通的 Anim Sequence。

 

       第三種數(shù)據(jù)資源類型叫 Blendspace。他可以是一維的也可以是二維的。二維的情況下,在兩個(gè)軸上,通過變量控制對(duì)任意在二維平面上指定的動(dòng)畫序列(Anim sequence)作混合。對(duì)于任意的二維輸入,總能找到這個(gè)輸入值在二維圖像附近最接近的四個(gè)動(dòng)畫序列按照權(quán)重來(lái)混合。嚴(yán)格來(lái)說,Blendspace 并不是單純的基礎(chǔ)數(shù)據(jù),他也受其它輸入?yún)?shù)的影響來(lái)混合 Pose 。但是,由于在動(dòng)畫混合藍(lán)圖中是作為 Pose 的輸入結(jié)點(diǎn),我們這里依然把它作為數(shù)據(jù)類資源。

 

       第四種數(shù)據(jù)資源叫 Montage。這一類資源一般是直接受邏輯控制的組合資源。

 

       在數(shù)據(jù)資源的基礎(chǔ)上,我們還可以綁定一些額外的數(shù)據(jù)。

 

       第一類常用的數(shù)據(jù)類型叫 Notify。引擎包括一些內(nèi)建的 Notify類型。譬如,在走路的時(shí)候希望腳步踩到地面的那一刻,觸發(fā)踩地面的事件,用來(lái)向地面投射貼花,用于產(chǎn)生腳印,以及播放腳步音效或揚(yáng)起塵土的特效之類。這里的 Notify 你還可以擴(kuò)展成你自定義的事件類型,可以在藍(lán)圖以及代碼中去處理事件對(duì)應(yīng)的邏輯。舉個(gè)例子:如果做一個(gè)動(dòng)作或格斗類游戲,在出招的時(shí)候,判定并不是從這個(gè)動(dòng)畫開始播放的時(shí)刻就已經(jīng)有了的,可能是從出招動(dòng)畫到某一時(shí)刻開始,才有打擊判定。那么我們就可以通過 Notify 來(lái)用事件通知游戲邏輯在特定的時(shí)候去打開和關(guān)閉判定。

 

       第二類叫 Curve。Curve 就是伴隨動(dòng)畫序列的時(shí)間軸所綁定的曲線數(shù)據(jù),后面會(huì)有一些舉例。再然后你也可以綁定一些你自定義的數(shù)據(jù)類型。

 

112520omtkujtcv3sydk3d

?

?        講完剛剛這些數(shù)據(jù)類型,接下來(lái)就是最重要的處理動(dòng)畫混合邏輯的資源,叫 Anim instance。Anim sequence 的設(shè)計(jì)是基于對(duì)于 3A 級(jí)游戲中復(fù)雜的動(dòng)畫需求所產(chǎn)生。這里有一個(gè)假設(shè),那就是動(dòng)畫狀態(tài)在復(fù)雜的情況下一定是需要對(duì)骨骼結(jié)構(gòu)有認(rèn)知的。所以引擎中的 Anim instance 和骨骼是強(qiáng)耦合的關(guān)系。譬如你需要知道腰部的骨骼位置來(lái)區(qū)別開上半身和下半身的動(dòng)畫,這樣的設(shè)計(jì)可以完成相當(dāng)復(fù)雜的動(dòng)畫混合,但是卻也帶來(lái)了一些限制。如果我的整個(gè)動(dòng)畫狀態(tài)只需要簡(jiǎn)單的一個(gè)狀態(tài)機(jī)在不同的狀態(tài)中,譬如閑置、追逐、攻擊、受擊、死亡,在每中狀態(tài)中,并不作復(fù)雜的混合,而只是播放一個(gè)簡(jiǎn)單的 Anim instance。在整個(gè)邏輯中完全不需要用到骨骼信息。那么照理來(lái)說,即使擁有不同骨骼結(jié)構(gòu)的對(duì)象,如果只需要這個(gè)簡(jiǎn)單邏輯的話都可以共享這套邏輯。然而由于我剛剛所說的 Anim instance 和骨骼的強(qiáng)耦合設(shè)計(jì)導(dǎo)致在現(xiàn)在的引擎框架下,這樣的功能暫時(shí)無(wú)法完成。我們?cè)趦?nèi)部也在作一些討論,以后可能會(huì)有支持純邏輯的 Anim instance 功能,而目前來(lái)看,如果大家有這樣的需求,我建議在可能的情況下把這些對(duì)象的骨骼層次結(jié)構(gòu)盡可能保持一致,這并不是說多個(gè)對(duì)象的骷髏要完全一致,而只是骨骼樹的層次結(jié)構(gòu)一致就可以了。譬如你的基礎(chǔ)骨骼是個(gè)人形,有些怪物會(huì)多出尾巴或翅膀,這些多出的骨骼并不破壞原先的樹狀結(jié)構(gòu),而只是多出來(lái)的分支。所以還是可以利用 Retargeting 來(lái)共享 Anim instance 的邏輯。

 

112520luobl969mf9mfmnf

?        Anim instance 中,最明顯的兩塊分別是 EventGraph 和 AnimGraph。其中 EventGraph 就類似于普通的藍(lán)圖,用來(lái)在 tick 的時(shí)候處理一些邏輯狀態(tài)的更新以及播放 Montage。當(dāng)然這些邏輯也可以在 C++里面做。AnimGraph 是用來(lái)混合和輸出 Pose 的地方。說到混合,我們可以把每一幀中整個(gè)混合的過程看成是一棵樹,從葉子結(jié)點(diǎn)輸出的 Pose 經(jīng)過枝干結(jié)點(diǎn)的混合計(jì)算輸出到根結(jié)點(diǎn)的最終 Pose。我們剛剛說到的數(shù)據(jù)類的資源,就是這里所謂的葉子結(jié)點(diǎn)。這些結(jié)點(diǎn)本身不需要其它的 Pose 作為輸入,而直接提供了 Pose 的輸出。而枝干結(jié)點(diǎn)則是進(jìn)行混合的結(jié)點(diǎn),當(dāng)然真的說混合也不是很準(zhǔn)確,有些枝干結(jié)點(diǎn)只需要輸入一個(gè) Pose,在自己的結(jié)點(diǎn)邏輯中,對(duì)這個(gè) Pose 作一些修正,并不進(jìn)行混合。我們把這些枝干結(jié)點(diǎn)計(jì)算調(diào)整和混合 Pose 的行為稱作評(píng)估(evaluate)。舉個(gè)最簡(jiǎn)單的枝干結(jié)點(diǎn)的例子,那就是多結(jié)點(diǎn)混合。譬如,輸入的有兩個(gè) Pose ,一個(gè)權(quán)重是 0.8,另一個(gè)是 0.2,相當(dāng)于是把第一個(gè) Pose 的 BoneMap 的 transform 乘以 0.8,第二個(gè)乘以 0.2,再相加輸出。這里我列了一個(gè)樹狀圖,來(lái)表示動(dòng)畫混合的過程。但是因?yàn)檫@是個(gè)非常簡(jiǎn)化了的例子,所以其中不包括直接對(duì)骨骼進(jìn)行控制或者直接 Override 一個(gè) Fullbody slot 來(lái)強(qiáng)制更新整個(gè) BoneMap 之類的行為。并且一般來(lái)說,一個(gè)正常的 anim graph 的一幀的混合也不會(huì)像這張簡(jiǎn)化圖這樣是棵紅黑樹。首先,就像我剛剛說的,你并不能保證他是二叉的,譬如剛剛說的多混合結(jié)點(diǎn)完全可以由三個(gè)或以上結(jié)點(diǎn)來(lái)混合,以及我剛剛說的有些枝干結(jié)點(diǎn),只有一個(gè)輸入。再者,大部分情況下他也不會(huì)是平衡的。在混合狀態(tài)復(fù)雜的情況下,我們一般會(huì)分層次來(lái)混合,這就導(dǎo)致了這棵混合樹會(huì)往一個(gè)分支方向衍生出去。

112520slx8kdlyekvkswf2


       好了,那么剛剛看到的是單幀的 Pose 混合計(jì)算情況。當(dāng)持續(xù)到多幀以后,情況又會(huì)稍微復(fù)雜一些。譬如說兩個(gè) Pose 混合起來(lái),他們的長(zhǎng)度很有可能不一樣。舉例,我有一個(gè)走路的動(dòng)畫,他可能長(zhǎng)達(dá) 2 秒,同時(shí)我又有一個(gè)跑步的動(dòng)畫,他長(zhǎng)達(dá) 1 秒。如果我直接混合,就會(huì)出現(xiàn)很怪異的情況,譬如走路還在邁左腿的時(shí)候,跑步已經(jīng)邁右腿了,混合起來(lái)的姿勢(shì)就會(huì)非常奇怪。基于這種情況,我們引入了 Sync Groups 的概念,當(dāng)我們?cè)O(shè)置這兩個(gè)動(dòng)畫序列在同一個(gè) Sync Groups 下進(jìn)行混合時(shí),引擎會(huì)把當(dāng)前混合時(shí)權(quán)重較高的作為領(lǐng)導(dǎo),把剩下的序列縮放到和領(lǐng)導(dǎo)序列一樣長(zhǎng)的情況,再按比例去做混合。這樣就能解決動(dòng)畫長(zhǎng)度不一致的混合問題。

 

112520c4vjql5jjll9qgj8


       再來(lái)看多幀動(dòng)畫狀態(tài)下,如果狀態(tài)復(fù)雜,動(dòng)畫樹上的某些分支在不同的幀內(nèi)是完全不同的狀態(tài)。為了簡(jiǎn)化樹的邏輯,動(dòng)畫混合系統(tǒng)中可以使用狀態(tài)機(jī)來(lái)隔離每一幀的狀態(tài)。我這里的圖例舉了一個(gè)比較簡(jiǎn)單的 Locomotion 的狀態(tài)機(jī)。

 

       關(guān)于動(dòng)畫混合的這棵樹,在復(fù)雜的情況下,我們還會(huì)把他做分層。也就是把一棵混合完的樹的根結(jié)點(diǎn)緩存下來(lái),作為另一棵樹的葉子結(jié)點(diǎn)。當(dāng)然你也可以把整個(gè)復(fù)雜的樹連到一起,分層只是為了便于維護(hù)和調(diào)整。這個(gè)圖片是我們的 MOBA 游戲《虛幻爭(zhēng)霸》中一個(gè)角色分層混合的模版示例。


112521qh5m9fyv9clifylf

?講完了動(dòng)畫的基礎(chǔ)概念后,我們來(lái)看一些例子加深理解。

 

112521k82n352h5gldi8d2

 

       子樹類用例。在引擎中有一類功能叫 Sub anim instance。這就類似于剛剛說到分層里面的一棵子樹,這個(gè)子樹可以擁有一個(gè)輸入結(jié)點(diǎn),并且輸出一個(gè) Pose 。典型的應(yīng)用方式,是把在同一個(gè)邏輯下有多種可替換的子邏輯分離開,做到不同的 Sub anim instance 中。這樣可以把剩余的邏輯用來(lái)共享。通過替換不同的 Sub anim instance 來(lái)組合出最終不同的效果。

 

112521ysc77hxsq7qhdxtp

 

       接下來(lái)講一些葉子類的用例。通常的葉子類結(jié)點(diǎn)就是我們剛剛說的數(shù)據(jù)類結(jié)點(diǎn),我這里舉兩個(gè)比較特殊的例子。在 4.17 版本中,我們會(huì)加入一個(gè)叫 live link 的結(jié)點(diǎn)。它通過引擎的消息總線從外部實(shí)時(shí)讀入數(shù)據(jù)輸出 Pose 。這里的輸入源可以是各種 DCC 工具,也可以是動(dòng)作捕捉或手勢(shì)識(shí)別類設(shè)備。在我們放出的第一個(gè)版本中,會(huì)帶有一個(gè) maya 的實(shí)現(xiàn),通過 maya 的插件把在 maya 中當(dāng)前動(dòng)畫的 BoneMap 數(shù)據(jù)通過 live link 消息總線和引擎進(jìn)行通信。引擎把接收到的數(shù)據(jù)轉(zhuǎn)換成引擎內(nèi)的數(shù)據(jù)輸出當(dāng)前的 Pose 。這樣就可以做到在 maya 中一邊播動(dòng)畫一邊在引擎中看到效果了。

 

112521bjnnr0cp5vndqf88


        下一個(gè)葉子類結(jié)點(diǎn)的舉例,叫 Pose Snapshot。Pose Snapshot 就是把任意指定幀的 BoneMap 記錄下來(lái),在接下來(lái)的任意時(shí)刻,用來(lái)作為數(shù)據(jù)源輸入和其它 Pose 做混合。譬如在 Robo Recall 中,你打倒了機(jī)器人,機(jī)器人會(huì)進(jìn)入物理狀態(tài)而倒地。你可以把這個(gè)狀態(tài)存下來(lái),在之后再和站起來(lái)的動(dòng)畫作混合。

 

        剛剛舉了兩個(gè)葉子類結(jié)點(diǎn)的例子,我們?cè)賮?lái)看看動(dòng)畫混合中最大的一類——枝干類結(jié)點(diǎn)的例子。大部分情況都是多個(gè) Pose 按權(quán)重進(jìn)行混合,當(dāng)然也可以是按照 bool、int、enum 值進(jìn)行混合。我這里依然舉一些特殊的例子。


112522coj17o01070gjkx4

 

?       第一個(gè)例子是 RigidBody 結(jié)點(diǎn)。在講這個(gè)結(jié)點(diǎn)前,我要先介紹一個(gè)伴隨而來(lái)的概念,叫 immediate mode physics。引擎中以前的 Physics 是所有的 RigidBody 都加到同一個(gè) PhysX scene,這種情況下如果每個(gè)角色身上都有多個(gè)需要計(jì)算物理的 RigidBody,場(chǎng)景中又有大量的這樣的角色,計(jì)算量就相當(dāng)?shù)拇蟆5谴蟛糠謺r(shí)候角色互相之間的物理碰撞細(xì)節(jié)大家并不關(guān)心,所以這樣的效率比較低。

 

112522g8zt4zmm7fmzgq72


?       因此我們和 Nvidia 進(jìn)行了合作,他們對(duì) PhysX 的 Api 進(jìn)行了調(diào)整。在新版本中放出了更底層的 Api 可以讓我們?cè)谝嬷凶龈?xì)致的控制。大家可以看到這個(gè)新的 immediate physics,一個(gè)角色身上所有的 RigidBody 都只注冊(cè)在當(dāng)前這個(gè) skeletal mesh component 下,多個(gè) SMC(skeletal mesh component 縮寫)之間并不會(huì)有交互,這樣很大程度上提高了運(yùn)行的效率。

 

112522r2auwpos2svuwarg

 

       大家可以看到,這里的視頻同屏有幾百個(gè)小兵站在地上做閑置的動(dòng)畫,在受到物理沖擊后轉(zhuǎn)入到物理狀態(tài)。這么大量的物理對(duì)象在我的筆記本上依然能穩(wěn)定在 60 幀,而右邊的圖也顯示了單個(gè)較為復(fù)雜的角色在模擬物理時(shí)候的開銷,只使用了 0.24ms。大家可能覺得這是一個(gè)純粹物理的功能,為什么我放到動(dòng)畫的枝干結(jié)點(diǎn)的例子里來(lái)講呢? 因?yàn)槭聦?shí)上你可以在動(dòng)畫中把動(dòng)畫計(jì)算完的 Pose 輸入進(jìn)去,在這個(gè)結(jié)點(diǎn)中根據(jù)當(dāng)前動(dòng)畫的 Pose 和前一幀計(jì)算完的結(jié)果計(jì)算出骨骼結(jié)點(diǎn)的變化,從而模擬出物理受力的變化,并根據(jù)輸入的權(quán)重混合回你的 Pose 。有了這樣的功能,做我之前說的 Robo Recall 中很自然的擊倒機(jī)器人或者拳擊類的游戲、以及用槍射擊怪物時(shí)怪物比較自然的受擊都變得相當(dāng)簡(jiǎn)單。


112522xiua66eu6i6neau6

 

       好了,下面我們?cè)賮?lái)看另一個(gè)枝干結(jié)點(diǎn)的例子。我們稱之為 Speed Warping。傳統(tǒng)的游戲中如果你調(diào)整了移動(dòng)速度,那么為了不產(chǎn)生滑步你也需要調(diào)整跑步的動(dòng)畫播放的速率。譬如你的速度翻了一倍,那么很多時(shí)候你就需要把動(dòng)畫也加快一倍播放,大家可以看到在這里的視頻右邊加快播放后的動(dòng)畫其實(shí)是很別扭的。真實(shí)情況下我們提高速度除了邁出的腳步速度會(huì)有一些變快以外,更多的情況下,其實(shí)是調(diào)快了步幅。同樣的減慢速度也是這樣。所以 Speed Warping 就是做了這么一個(gè)效果。那我們是怎么計(jì)算的呢??

 

112522rbvwp6hrisi1v3si

 

?       簡(jiǎn)單來(lái)講,原始的動(dòng)畫雙腳的位置是這里的紅球。我們計(jì)算他跟腰部垂線的水平距離并根據(jù)加減速的倍率橫向擴(kuò)展。譬如當(dāng)是 2 倍的時(shí)候,調(diào)整到綠球的位置。但這個(gè)時(shí)候兩只腳的距離被拉的太長(zhǎng)了,因此我們適當(dāng)?shù)耐抡{(diào)整了屁股的位置,并且將兩只腳以剛才綠球所在位置到屁股的連線上挪動(dòng)一段距離使得腳步的長(zhǎng)度保持不變,所以最終計(jì)算出來(lái)的就是藍(lán)球的位置。

 

112523lr399u3ev1epo3te


       我再舉一些其它的例子。比如引擎中當(dāng)你對(duì) AnimBP 進(jìn)行繼承的時(shí)候,所創(chuàng)建出來(lái)的內(nèi)容叫 Child AnimBP ——它所做的事情是讓你重載所有的葉子類結(jié)點(diǎn)。舉個(gè)實(shí)用的例子:譬如我有一種敵人,他永遠(yuǎn)是從初始的出現(xiàn)狀態(tài)到發(fā)現(xiàn)玩家到向玩家攻擊這樣轉(zhuǎn)化,而這樣的怪物在地圖上不同的場(chǎng)景下有不同的出現(xiàn)動(dòng)畫,有可能是從地上爬出來(lái)的,有可能是從墻上跳出來(lái)的。對(duì)于這個(gè)怪物來(lái)說,他的動(dòng)畫切換狀態(tài)都是一樣的,所不同的只是初始狀態(tài)所需要使用的資源,所以只需要替換初始的動(dòng)畫(某個(gè)葉子結(jié)點(diǎn))就可以了。

 

112523z73ll555pbggk7m1

 

       再舉一個(gè)例子,有不少人問過,在《虛幻爭(zhēng)霸》中,是怎么做到讓角色不滑步的。傳統(tǒng)的主機(jī)游戲中,為了讓腳不滑步很多時(shí)候我們都是使用 root motion 來(lái)做移動(dòng)的動(dòng)畫。但是因?yàn)椤短摶脿?zhēng)霸》是個(gè) MOBA 游戲,策劃會(huì)希望能夠用數(shù)據(jù)來(lái)驅(qū)動(dòng)移動(dòng)的速度。譬如在有不同的 buff 或者裝備的情況下,角色的速度也會(huì)發(fā)生變化,這用 root motion 就很不好處理。所以我們做了一個(gè)叫 Distance Curve 的功能,這也是我剛剛說到的 Curve 數(shù)據(jù)的一種運(yùn)用方式。我們可以把 Distance Curve 的方式看成是反向的 root motion。它通過給所有的啟動(dòng)、旋轉(zhuǎn)、站定動(dòng)畫都加入曲線數(shù)據(jù),曲線上的數(shù)值表示當(dāng)前這幀動(dòng)畫到達(dá)站定點(diǎn)的位置的距離,其中站定點(diǎn)(Marker)是很容易預(yù)測(cè)的。?

 

 

112523k3ww6f3l11wnnjwp

 

相關(guān)文章
網(wǎng)友評(píng)論

您需要登錄后才可以發(fā)帖 登錄 | 立即注冊(cè)

關(guān)閉

全部評(píng)論:0條

推薦
熱門