圖形引擎實戰(zhàn):Unity角色攀爬系統(tǒng)
本篇內容技術參考借鑒了Invector和Dias的角色控制方案,動畫資源來自Maximo;
1.檢測可攀爬物體
基本思路是先用射線檢測去檢測角色正前方是否有碰撞體,再進一步檢測前方是否有障礙,碰撞體是否符合攀爬標準:
標記,可攀爬的物體可以單獨一個Layer或者使用Tag標記方便管理;
表面角度,可攀爬的角度可以設置到45度以上;
附近無障礙,目標點周圍至少人物寬度附近沒有障礙且均可攀爬;
碰撞檢測使用Physics.Linecast或者Physics.SphereCast都可以;
動圖見鏈接:https://zhuanlan.zhihu.com/p/563121983
2.進入攀爬狀態(tài)
進入攀爬狀態(tài)時播放進入動作,首先要對齊位置,將角色位置移動到合適和距離和朝向避免播放進入動作時穿模;
動圖見鏈接:https://zhuanlan.zhihu.com/p/563121983
在角色上以角色根節(jié)點為參照偏移存儲一個位置,也可以直接掛一個空物體作為攀爬的參考點,這個點就作為需要對齊的位置;對齊過程可以使用協(xié)程來漸進式的對齊位置,避免位置跳變;
進入動作播放完畢后,記得關閉角色Rigidbody的重力,并開啟Is Kinematic,避免剛體速度帶來不必要的麻煩,后續(xù)攀爬過程中直接改變Tranform來實現位移,不再使用速度控制位移;
3.攀爬四方向移動
移動時需要實時的查詢移動方向上是否可攀爬,此時的檢測的方式為,先向角色的移動方向檢測一小段距離是否有可攀爬碰撞(為應對內倒角型轉角),若無碰撞再以此為起點,向墻面打射線檢測;
由于墻面的不規(guī)則性和為應對外倒角型轉角,在第二階段檢測時會檢測不到側面的墻體,可以在原本垂直墻面的方向的基礎上朝移動方向的反方向偏移一定角度檢測;
另外避免障礙使角色穿模,在角色移動前先向目標方向使用Physics.CapsuleCast在沒有障礙碰撞時再移動;
動圖見鏈接:https://zhuanlan.zhihu.com/p/563121983
四方向的移動使用blendtree,在控制腳本中通過OnAnimatorMove函數應用 rootmotion:
通過 tranfrom.InverseTransformPoint(animator.rootPosition)可以獲取當前動畫的位移位置,只取該位移中的x,z分量加上當前的位置作為目標位置;然后通過lerp的方式修改當前position;
關于攀爬速度調整,因為移動是基于rootmotion的,所以直接通過設置動畫的播放速度就可以直接調整攀爬速度且手和腳不會明顯滑動;
如果想要角色僅在有輸入時才有移動動作,無輸入時定格在當前的姿勢,可以將輸入的大?。╩agnitude)作為blendtree的播放速度,當無輸入時就會停止播放;
動圖見鏈接:https://zhuanlan.zhihu.com/p/563121983
4.攀爬四方向跳躍
檢測跳躍的基本邏輯和檢測是否可以移動類似,在輸入方向上檢測跳躍距離處是否可攀爬,另外需要檢測跳躍路徑上是否有阻擋,可以使用SphereCast或者在角色Y軸方向上分多段射線檢測;
檢測跳躍距離時,先從輸入方向 * 跳躍距離處向角色前向檢測是否有可攀爬位置,因為墻面不平整的原因每次跳躍都不會是固定距離,所以需要記錄跳躍目標位置,在播放動畫時將角色位置漸進移動到目標處,這一步可以在OnAnimatorMove中當角色處于跳躍狀態(tài)時按當前動畫的進度移動根位置;
動圖見鏈接:https://zhuanlan.zhihu.com/p/563121983
5.調整角色姿態(tài)
墻面凹凸不平時,希望角色能夠貼合墻體表面的角度,通過raycastHit.normal表面法線信息獲得墻面角度,這可以用來調整角色Y軸方向的旋轉使其貼合墻面;
只用一個點的法線來調整旋轉角度是不夠的,還需要在X軸方向的旋轉角度貼合。想要角色Y方向上整體貼合墻面,可以從角色腿部或者腳部向墻面檢測一個點,取此點和攀爬點的連線的角度作為基準,調整角色Z軸方向旋轉使其貼合;
動圖見鏈接:https://zhuanlan.zhihu.com/p/563121983
6.手部和腳部的Ik調整
IK部分的實現同樣也可以通過手部和腳部向墻面檢測碰撞位置,將一定范圍內碰撞位置作為IKPosition賦值給Animator;
手部和腳部的位置可以通過
transform.InverseTransformPoint(animator.GetBoneTransform(HumanBodyBones.LeftHand).position)函數獲?。?/p>
7.頂部攀爬退出/懸掛狀態(tài)
到達墻壁的頂部后,同樣使用射線檢測頂部是否達到攀頂的條件(障礙、角度、地面等條件):
①.由角色胸部向上檢測是否有障礙,可以移動;
②.由第一步檢測結束位置向前檢測是否有障礙;
③.由第二步結束位置向下檢測地面,作為攀頂動作的參考點;
與進入攀爬時類似,在動畫播放前對其位置(主要是角色離頂部的高度);
動圖見鏈接:https://zhuanlan.zhihu.com/p/563121983
在頂部有直角型的阻擋時可以切換攀爬到懸掛狀態(tài),此時的檢測方向則變?yōu)橄蛏蠙z測懸掛點,移動時疊加移動方向的偏移預先檢測前方是否有可懸掛的點;
動圖見鏈接:https://zhuanlan.zhihu.com/p/563121983
8.不同高度的地形跨越:
針對不同高度的障礙,對應不同的動畫跨越;
動圖見鏈接:https://zhuanlan.zhihu.com/p/563121983
對應最低高度的平臺希望讓角色直接走/跑上去,不需要特殊的動畫,嘗試過播放單獨的抬腳動畫反而不連貫;對于這種類似臺階高度的障礙,如果不做處理可能會由于剛體碰撞而卡住。這里我們先通過腳部向上一點的位置發(fā)射射線檢測是否有臺階存在,進一步從一定高度向前延申然后向下射線檢測獲得臺階高度,然后將角色的移動速度映射到根節(jié)點與臺階邊緣連線的方向上。這樣角色將會獲得斜向上的速度,順利跨上臺階;
動圖見鏈接:https://zhuanlan.zhihu.com/p/563121983
其他高度的地形障礙檢測方式與前面的所提到的類似,先檢測到障礙的存在,再從上方向下獲得高度,并確認目標點周未空間是否允許跨越;接下來將角色位置調整到合適的位置,動畫播放過程中使用matchtarget將手部或者腳部貼合障礙物的頂端。
關于角色動畫切換:
1.直接使用動畫狀態(tài)機中的條件切換:
2.在控制腳本中, 調用Animator相關函數實現切換:
Animator.CrossFade 或者Animator.CrossFadeInFixedTime;
使用第一種方式就需要現在動畫控制器界面連線并設置切換條件,并且在控制腳本中為animator賦值才能切換動畫,第二種方式更加靈活,不用向animator賦值就可以無條件切換;
當然如果使用Animancer這種playable實現的動畫播放器則只需要設置播放相關的動畫片段即可。
動畫位置匹配:
1.使用Animator.MatchTarget在動畫的某個階段將角色的某個位置匹配到響應位置;
2.在動畫階段直接修改角色的Transform將角色移動到合適的位置,一般會在動畫播放開始前;
歡迎加入我們!
感興趣的同學可以投遞簡歷至:CYouEngine@cyou-inc.com
帶來游戲引擎最新知識和內容