Advanced Locomotion System V3是虛幻商城的一款第三方插件。它相比UE4的基礎走跑跳表現,實現了更多動作游戲里常用的運動特性,雖然價格定價不菲,依然備受關注。筆者試用了這款插件,確實很強大,適合作為基礎插件來做FPS,ACT游戲,因此簡單學習分析下這款插件。
插件特點:
- 具備動作游戲的常見特性,支持多種移動模式,步行,奔跑,沖刺,下蹲,Ragdoll
- 運動細節做得很到位,包括原地轉身,奔跑急停轉向,移動中身體傾斜,落地腿部緩沖,頭部Aim Offset(AO),腿部IK
- 支持網絡同步
- 純藍圖實現,適合策划、開發學習應用
動畫樹分析
插件用了兩顆動畫樹,Mannequin_AnimBP和Mannequin_IK_AnimBP,前者掛載在人物Blueprint上,用來處理人物主體動畫;后者掛載在人物的Skeletal Mesh上,用作動畫后處理來實現腳部IK動畫。Mannequin_AnimBP動畫樹大體分為地面動作、空中動作兩部分的處理。其中地面Locomotion的表現需求是最多的。
地面Locomotion
地面Locomotion算是動畫樹最復雜的狀態機了,可以簡單分為3層:
可以看到第一層狀態機只是對第二層狀態機輸出動畫做了一個呼吸動畫的疊加。第二層狀態機輸出的Idle動畫其實是靜止Pose,在這一層才統一疊加上呼吸動畫。
第二層狀態機只定義了幾種Locomotion狀態的過渡邏輯,可以看到Locomotion有走停轉站四種狀態。
第三層狀態機分別是走停轉站的動畫實現,其中走(Moving)的實現是最為復雜的。可以看到狀態機有很多動畫分支,全部是用BlendSpace,以Direction,Gait Value作為輸入值來輸出移動動畫的。在此簡單解釋Gait Value,插件設計該變量將Walk/Run/Sprint三類狀態的速度值映射為[1,3],動畫機內只關注跟Walk/Run/Sprint狀態相關的Gait Value,無須關注具體速度值。
人物有兩種轉身模式,一種是根據人物速度方向轉身(Velocity Direction Mode),一種是根據鏡頭方向轉身(Looking Direction Mode),這兩種轉身模式也造就了兩種移動模式,通常適用於在ACT/FPS游戲里切換格斗/射擊和自由移動兩種移動模式。轉身模式通過變量ALS_RotationMode控制。
八方向移動
以人物速度方向轉身的移動動畫比較簡單,基本只需要對朝前的Walk/Run/Sprint動畫做BlendSpace融合即可。以鏡頭方向轉身的移動動畫則要做八方向移動動畫,簡單的八方向動畫(前/后/左/右/左前/左后/右前/右后方向移動)其實用一個BlendSpace就可以實現,但插件做了更復雜的八方向動畫。左右移動進一步細分出了左移姿勢前進,左移姿勢后退,右移姿勢前進,右移姿勢后退等四個動作,用了兩個BlendSpace來實現這種八方向移動。
狀態機根據人物移動方向切換使用兩個BlendSpace,當鏡頭與速度方向夾角處於[-90,90]范圍內用前進BlendSpace,否則用后退BlendSpace。上圖紅框部分是兩個BlendSpace實際采用區域。
該狀態機還有個分支用於輸出下蹲移動動作,移動速度是恆定的,所以用了1D BlendSpace做輸出,比較簡單,不展開細說。
另外整個狀態機很多分支都有RF變量身影,該變量意思是移動動畫是以左腳還是右腳在前,因此以RF變量可以分出了兩種BlendSpace。
移動傾斜
根據Lean Gounded X/Lean Gounded Y變量可以BlendSpace出一個身體向左右,前后傾斜一定角度的Pose,將其與移動動畫做融合,就能表現出角色傾斜奔跑的效果。這個融合主要是為了體現角色速度感。角色速度,每幀速度角度變化值決定左右傾斜度,每幀角色速度變化值決定前后傾斜度。
正常停止移動動畫
從Moving到NotMoving有兩種過渡,一種是正常停止移動的Stop動畫,一種是奔跑急停的Pivot動畫。Stop動畫細分了多種狀態下的Stop動畫,這里只看普通跑動下的Stop動畫。
可以看到Stop動畫是由2個BlendSpace輸出的,根據左腳在前,還是右腳在前,決定使用哪一個BlendSpace。兩個BlendSpace都接收Feet Position X和Feet Position Y作為輸入。
Feet Position X:表示Foot Direction,Foot Direction的范圍是[-90,90],表示移動方向。
Feet Position Y:表示Foot Position。Foot Position的范圍為[-1,1],其中左腳邁到最前時為-1,右腳邁到最前時為1,兩腿剛好交叉時為0。看上圖可知當Foot Position>0時,即右腳邁在前面時,用ALS_N_Stop_RF BlendSpace,否則用ALS_N_Stop_LF BlendSpace。
Feet Position X、Feet Position Y兩個變量值的更新很巧妙:所有的移動Animation Sequence上,都添加了名為FootDirection,FootPosition的Curve,記錄了每一幀的腳步位置和移動方向。當進入Stop狀態時,通過GetCurveValue接口獲取FootDirection,FootPosition的Curve值,再設置給Feet Position X、Feet Position Y。
Stop的BlendSpace基本就是采樣了人物在左移,右移,前行3個方向下,左腳或右腳在前的腳步回收動畫,可以讓人物在停止移動時,有一個明顯收住腳部,回撤站立的表現,增強人物運動真實感。
奔跑急停動畫
增加奔跑急停的Pivot動畫用於人物跑動中大幅度轉向的過渡,進一步強化運動速度感。判斷移動輸入方向與人物移動方向的Yaw角度大於100(基本就是反向移動)時,人物在地面上且速度處於一定范圍內,即進入Pivot過渡。
原地轉身動畫
插件沒有在AnimGraph里播放原地轉身動畫,而是在EventGraph里調用Play Montage接口播放TurnInPlace的Montage動畫,在AnimGraph里添加TurnInPlace Slot輸出轉身動畫。
看下動畫樹的EventGraph里調用轉身動畫的接口:
決定是否播放轉身動畫主要靠以下3個變量:
Turning In Place:當前是否正在轉身
Turning Right:當前是否正在向右側轉身
Aim Yaw Delta:當前幀鏡頭朝向與人物朝向的Yaw角變化值
基本邏輯是轉動鏡頭Yaw角大於90度轉身或180度轉身閾值時,且當前沒有在轉身,則播放轉身動畫;當前已在轉身中,只可以打斷往相反方向轉身。這樣避免持續往一側轉動鏡頭時,播轉身動畫過程中,出現打斷動畫,重頭播轉身動畫的情況。
轉身動畫只有腿部動作,不帶人物轉向,人物轉向通過TurnInPlace_AnimNotifyState動畫事件每幀設置。
每幀設置轉向用一個EaseInOut曲線來控制,獲取上一幀跟當前幀的曲線差值,即為當前幀人物轉向Yaw角偏移值。
最后,TurnInPlace_AnimNotifyState動畫事件還需每幀判斷當前人物是否有移動,移動則打斷轉身動畫。
空中動作
起跳動作
起跳動作用了基礎起跳動作,融合BlendSpace,讓起跳呈一定程度的Lean傾斜,表現出人物往對應方向起跳的感覺。其中Lean In Air值由跳躍Z軸速度和移動速度決定,Direction為移動速度方向。
下落動作
下落動作有兩個階段動作,一開始是正常騰空下落,隨着下降速度變大,逐漸Blend為手腳胡亂擺動的動作,用一個EaseInOut曲線控制Blend速度。
下落動作同樣融合BlendSapce做Lean傾斜,並且會計算着地時機,在快着地前融合一個人物手臂上揚再下落的動作,強化落地沖擊感。該融合靠Land Prediction Alpha變量控制。該變量在人物下落過程中,每幀以腳部為圓心做球形檢測,得出球形與地面的相交最短距離,歸一化到[0,1]的范圍值來做動畫融合。
落地動畫
人物跳躍着地后播放一個着地過渡動畫,當然如果在此期間人物移動則打斷過渡動畫。
頭部AO
頭部AO比較簡單,在MainStateMachine動畫輸出后,根據人物朝向和攝像機朝向計算出AimOffset值,做一個[-180,180] Yaw角,[-90,90] Pitch角范圍的AO處理。
Ragdoll系統
人物死亡后會切換為Ragdoll狀態,動畫狀態機比較簡單,根據人物是否處於奔跑,播放手腳亂擺或者身體蜷縮的動畫。Ragdoll系統更多在於藍圖里的邏輯處理。
切換Ragdoll狀態
進入Ragdoll狀態,做以下處理:
- 角色骨骼運動改由Skeletal Mesh,pelvis節點下的骨骼自行進行模擬物理
- 角色MovementMode切為None,讓MovementComponents不再更新角色位置邏輯
- 開啟角色網格碰撞,禁用角色膠囊體碰撞
每幀Update做以下處理:
- 判斷人物Z軸速度小於-4000時,關閉重力模擬,防止下落速度過快導致剛體穿透
- 更新Ragdoll的速度,更新pelvis bone的位置和旋轉
- 更新Actor的位置和旋轉。因為Ragdoll狀態下MovementComponent不再更新角色位置邏輯了,得根據pelvis bone的位置和旋轉計算並設置Actor的位置和旋轉,否則攝像機就不能正確跟隨角色Ragdoll了。
這里還要注意一些細節,不能直接以Pelvis Bone來設置Actor位置,如果直接設置,當角色Ragdoll倒地后,膠囊體其實有一半嵌入了地面。當退出Ragdoll時,膠囊體會瞬間彈出地面,導致人物抖動。解決辦法是從Pelvis Bone往Z軸負方向(地面)做SapsuleHalfHeight距離的射線檢測,SapsuleHalfHeight減去射線碰撞距離得出Z軸補償值,再取Pelvis Bone位置作為Actor位置,目的就是保證膠囊體不嵌入地面。
角色膠囊體始終只旋轉Yaw角,Roll、Pitch角為0,因此Actor旋轉只取Pelvis旋轉的Yaw角,這里注意角色正面/背面倒地后,起身的朝向剛好是相反的,通過判斷Pelvis的Roll角是否大於0,翻轉Yaw角180度即可。
退出Ragdoll狀態
退出Ragdoll則要恢復進入Ragdoll時所作的改動,並且播放起身動畫:
- 取消骨骼模擬物理
- 視乎角色是在地面還是空中,將Movement Mode切換為Walking/Falling
- 開啟角色膠囊體碰撞,禁用角色網格碰撞
- 設置角色Movement當前速度為Ragdoll速度
- 調用Anim Instance的Save Pose Snapshot接口,給當前角色動畫保存快照,在動畫機的退出Ragdoll狀態里,輸出這個快照
- 判斷角色面部朝上/朝下,播放對應起身動畫,角色以快照Pose開始起身站立
腿部IK
插件的腿部IK實現也挺不錯,單獨用了一個后處理動畫樹來實現,跟前面其他功能解耦,實現邏輯很清晰,也設計了一些變量來控制調整腿部IK效果。
插件的腿部IK實現了兩個基本功能:
- 左右腿自適應不同地面高度。站立在凹凸不平的地表上,左右腿能貼着地面站立,避免出現腿部懸空問題。
- 左右腳掌自適應不同地面角度。站立在斜坡上,人物腳掌要轉至與斜坡保持平行,緊貼地表。
簡單介紹下IK(Inverse Kinematics,逆向運動學)原理,它是與FK(Forawrd kinematics,正向運動學)
截然相反的一種骨骼定位技術。FK通過自頂向下確定每根骨骼的位置和旋轉,確定整個骨架形態。IK則是給某根骨骼指定位置旋轉,並自動計算其父骨骼的位置旋轉,從而確定骨架形態。
IK計算需要兩個參數,Joint Target和Effector。簡單理解,Effector其實就是我們想要修改的骨骼的目標點,由此引發的其父骨骼到Base骨骼之間的位置變動,則由IK自動計算出來。已知Base骨骼位置不變,如果只有Effector參數,IK計算出來的骨骼位置,在三維空間是有無數解的。因此還需要Joint Target參數,它相當於是一個參考點,讓IK計算得出的各骨骼位置盡量靠近這個參考點。
UE4的Anim Graph提供了Two Bone IK節點用於處理IK,需要設置進行IK的目標骨骼、Effector、Joint Target。
- 目標骨骼自然是兩條腿部骨骼:foot_l,foot_r。
- Effector以兩條腿部IK骨骼作為參考:ik_foot_l,ik_foot_r,這是官方骨架本身自帶的IK骨骼。除了腿部IK骨骼,官方骨架還自帶了手部IK骨骼,ik_hand_l,ik_hand_r。IK骨骼只是用於定位IK目標點的,並沒有綁定動畫。
- 由於腳部屈伸時,膝蓋肯定是朝前彎曲的,所以插件給Skeleton的左右腳各添加了從thigh(大腿)到calf(小腿肚)的虛擬骨骼:VB thigh_l_calf_l,VB thigh_r_calf_r,並將骨骼設置在膝蓋正前方30個單位的位置,作為Joint Target。
下圖就是Two Bone IK節點的對應設置:
游戲里隨着人物的運動,腿部IK Effector是一直在變的。因此需要每幀計算Effector值,動畫藍圖的計算過程如下:
- 首先雙腿分別向Z軸負方向(地面)做射線檢測,得出雙腿距離地面距離,看哪條腿距離地面更遠,將其距離值作為Pelvis Offset,把Pelvis(盆骨)骨骼向下移動Pelvis Offset單位,實際上也就是將整體人物骨骼下移,這樣靠下面的那條腿就站立在地面上了
- 接着計算兩條腿的Effector坐標,從而讓腿抬到地面位置。雙腿距離地面的距離,分別設為兩根IK骨骼的Z軸值,即可得出兩條腿Effector點的坐標
- 接着計算兩條腿的Effector旋轉,從而讓腳掌旋轉到適合角度,緊貼地面站立。根據射線與地面的碰撞點法線,可計算出碰撞地面的朝向,只取地面朝向的Roll角,Pitch角分量設給IK骨骼(Yaw角不用調整,讓腳掌始終朝前)。
得出以上關鍵數值后,Anim Graph里通過Transform(Modify)Bone節點修改各個關鍵骨骼數據,最后再通過Two Bone IK節點做IK計算:
這里還有個細節,每幀計算得出的數值與上一幀的數值進行插值后,再設置給骨骼,不做插值的結果就是人物上下樓梯會明顯抖動,就像下圖一樣:
結語
插件本身的功能已經挺豐富了,拿來做簡單的FPS、ACT游戲已經足夠。插件本身的設計架構也比較清晰合理,適合在此基礎上做重構,增加諸如持槍、匍匐等動作。就算不直接使用插件,插件諸如原地轉身、腳部IK的實現也是值得參考借鑒的。