用Unity實現彈反效果

遊資網發表於2019-09-23
用Unity實現彈反效果

大渣好。

老賊的黑魂系列,想必大家都樂(tong)在其中。

用Unity實現彈反效果

那麼要說到魂系列、乃至很多其他ACT要素濃郁的作品,最核心的機制之一,那就是彈反(視遊戲不同叫法也不同,一閃、完美防禦、彈開等等)。

實現了這個效果,(理論上)你也可以做一個類似的遊戲出來(強調:只是理論上,只是理論上)。


今天我們就用簡單粗暴的方法來實現一個彈反。

先看效果圖。


圖中可知:

  • 持續格擋,受擊時有晃動、硬直動作。
  • 完美格擋成功時(會根據攻擊方向進行格擋),敵人攻擊會被彈開。
  • 當敵人被彈開攻擊3次時,會進入後仰慢動作。


這次用的資源是在https://www.mixamo.com裡免費下的Great Sword Pack和Pro Sword And Shield Pack,需要的可以在工程裡邊拉或者自行下載。匯入資源後,用Plane和Cube隨便搭建一個場地。

由於這是一個簡單版的彈反功能實現,因此我們只需要製作兩個功能殘缺的工具人:一個只會左砍右砍的雙刀火雞哥,一個只能跑和防反的大劍姐。

一、雙劍角色

1.功能及動畫狀態機

雙劍角色作為被彈反的工具人,免費包裡沒有演出效果比較好的動畫,最終只好用同一個揮砍動畫(Slash)通過調節應用在三個狀態中(完美符合乞丐版氣息):左砍、右砍(映象)、被彈反(調節播放速度為負),自己有動畫的小夥伴請毫不猶豫地自行替換。

用Unity實現彈反效果

2.實現思路:

(1)在每個動畫快結束的時候執行動畫幀事件,隨機下一個Slash(揮刀)狀態,啟用對應攻擊源,用於判定攻擊方向。

(2)Slash時用動畫幀事件啟用武器上的觸發器。

(3)被彈反的時候,調節播放速度AnimaSpeed為,使其回放。

(4)當被彈反3次時觸發BehitBack後仰動畫。

3.相關設定

(1)角色設定

以下新增的Collider都勾選IsTrigger。

①給角色新增CapsuleCollider,然後調節至跟角色差不多大小。

用Unity實現彈反效果

②新增RigidBody,並勾選IsKinematic。

③展開角色的骨骼,分別給雙劍所在節點加上BoxCollier元件,並且調節至跟劍差不多大小,設定Tag為”EWeapon”,用於格擋時碰撞檢測。

④在劍的節點下邊新建一個空的物體SwordOri並新增Collider元件,設定Tag”為EWeaponOri”,作為攻擊源用於給玩家判定攻擊方向。

用Unity實現彈反效果

(2)設定動畫

因為需要一個後仰的慢動作,把BehitBack動畫的Speed調為0.5。

用Unity實現彈反效果

4.部分功能實現

(1)啟用武器的Collider

  • 雙擊Animator視窗裡的LSlash,展開Events,拖動動畫進度條。
  • 在手剛揮到角色前方的位置,點選Events下“+”,新增動畫幀事件(當動畫播放到這個位置時會執行對應名稱的方法),設定完成後Apply。


用Unity實現彈反效果

由於LSlash和RSlash使用的是同一個動畫,這裡通過獲取當前動畫狀態的名字的方式來判斷應該啟用哪邊的武器Collider,程式碼(含註釋)如下:

  1. //啟用武器Collider
  2.     public void OnAnimation_OpenSwordCollider()
  3.     {
  4.         if (beBlock)
  5.         {
  6.             return;
  7.         }
  8.         //獲取當前動畫資訊
  9.         aniInfo = animator.GetCurrentAnimatorStateInfo(0);

  10.         if (aniInfo.IsName("LSlash"))       //啟用左劍Collider
  11.         {
  12.             lSwordCollider.enabled = true;  
  13.         }
  14.         else if (aniInfo.IsName("RSlash"))  //啟用右劍Collider
  15.         {
  16.             rSwordCollider.enabled = true;
  17.         }
  18.     }
複製程式碼

同理,在砍動作結束時新增動畫幀事件關閉武器的Collider。

(2)被彈反

這次乞丐版的彈反實際上是Slash動畫的回放,所以只要播放速度為負即可,為了提升視覺效果,我們通過動畫曲線模擬先快後慢的彈開速度。

①設定動畫曲線

在指令碼中宣告一個變數public AnimationCurve animaSpeed,儲存後我們可以在Unity中找到這個變數,點選右側圖框便能編輯曲線。

用Unity實現彈反效果

橫軸將作為時間,豎軸將作為播放速度(具體引數按自己喜好調節):

用Unity實現彈反效果

②根據動畫曲線調節播放速度

  • 開啟Animator視窗,新增float型別引數AnimaSpeed。
  • 找到LSlash和RSlash兩個動畫狀態,分別勾選Speed下Multiplier的Parameter並選擇AnimSpeed,把動畫播放的速度與引數AnimaSpeed建立聯絡。
  • 通過AnimationCurve.Evaluate(float time)設定AnimaSpeed來調節播放速度。


用Unity實現彈反效果

程式碼(含註釋)如下:

  1. //被格擋時觸發動作回彈
  2.     public IEnumerator BeBlocked()
  3.     {
  4.         OnAnimation_CloseWeaponCollier();       //關閉武器碰撞盒
  5.         beBlock = true;                        
  6.         beBlockCounter += 1;                    //被彈反次數+1
  7.         timer = 0;
  8.         while (timer < 0.8f)                    //彈反動畫播放0.8s
  9.         {
  10.             SetAnimaSpeed();
  11.             yield return new WaitForFixedUpdate();
  12.         }
  13.         beBlock = false;
  14.         OnAnimation_RandomAState();             //隨機下一個狀態
  15.         animator.SetFloat("AnimaSpeed", 1);     //播放速度恢復正常
  16.     }

  17.     //設定格擋回彈時的速度
  18.     public void SetAnimaSpeed()
  19.     {      
  20.         timer += Time.fixedDeltaTime;                   //計時
  21.         animaSpeed = animaSpeedCur.Evaluate(timer);     //讀取曲線資料
  22.         animator.SetFloat("AnimaSpeed", animaSpeed);    //設定播放速度
  23.     }
複製程式碼

二、大劍角色

1.功能及動畫狀態機

大劍角色具有隻有格擋(完美格擋、持續格擋、受擊)和移動功能。

用Unity實現彈反效果

2.實現思路:

(1)點選右鍵,進入PerfectBlock狀態,根據敵人攻擊來方觸發對應的格擋動畫。

(2)當在PerfectBlock狀態下,敵人的武器碰到格擋Collider時會被彈反。

(3)按住右鍵進入KeepBlocking狀態,持續防禦。

(4)當在KeepBlocking狀態下,敵人的武器碰到格擋Collider時,玩家被擊晃動。

3.相關設定

(1)角色設定

以下新增的Collider都勾選IsTrigger。

①給角色新增Character Controller元件,用於實現移動。

②新增BoxCollider,調節大小與位置,使其位於角色前方,用於探測敵人和判定攻擊方向。

③展開角色骨骼,在武器節點下新建空的子物體BlockCollider並新增BoxCollider,用於格擋檢測,可以適量調大來增加格擋容錯率。

用Unity實現彈反效果

用Unity實現彈反效果

(2)動畫設定

當只有左方向的格擋動畫時,可以通過設定動畫狀態的Mirror(映象)屬性獲得右方向的格擋動畫。

拿PerfectBlock作為例子,在Animator新增一個Bool型別引數isRightB,在Inspector視窗如下圖設定:勾選Mirror右側Parameter,並選擇引數isRightB,表示當isRightB為true時播放映象。接下來只需在指令碼中控制isRightB的切換就可以控制左右格擋。

用Unity實現彈反效果

剩下的KeepBlock、BlockImpact、BlockEnd狀態也這樣操作,就可以獲得一套右格擋動畫。

4.部分功能實現

Block

(1)角色上的程式碼(含註釋)如下:

①敵人攻擊時,大劍角色前方的大Collider會檢測到敵人的SwordOri。

  1. private void OnTriggerEnter(Collider other)
  2.     {
  3.         if (other.CompareTag("Enemy"))                  //獲取敵人Transform
  4.         {
  5.             targetTrans = other.transform;
  6.         }

  7.         if (other.CompareTag("EWeaponOri"))             //檢測敵人攻擊時啟用的攻擊源Collider
  8.         {
  9.             eWeaponOriTrans = other.transform;
  10.         }
  11.     }
複製程式碼

②敵人攻擊時會啟用SwordOri,通過計算SwordOri與角色右方的夾角,決定格擋方向。


  1. //檢測攻擊方向
  2.     void CheckAttackDir(Vector3 eWeaponOriPos)
  3.     {
  4.         Vector3 aDir = eWeaponOriPos - transform.position;      //從玩家指向敵人攻擊源
  5.         float angle = Vector3.Angle(transform.right, aDir);     //計算aDir與角色右方的夾角
  6.         if (angle < 90)                                         //夾角<90度往右格擋
  7.         {
  8.             isRightB = true;                                    
  9.         }
  10.         else
  11.         {
  12.             isRightB = false;                                   //否則往左格擋
  13.         }
  14.     }
複製程式碼

③啟用blockCollider進行碰撞監測,並且根據攻擊來向播放相應的格擋動畫。

  1. //格擋
  2.     public void Block()
  3.     {
  4.         if (isFighting)                                 //如果戰鬥相關動畫在播放,則返回
  5.         {
  6.             return;
  7.         }

  8.         if (eWeaponOriTrans)                            //如果檢測到敵人攻擊源
  9.         {
  10.             CheckAttackDir(eWeaponOriTrans.position);   //檢測敵人攻擊方向
  11.         }

  12.         LookAtTarget();                                 //轉向目標
  13.         isBlocking = true;
  14.         isPerfectBlock = true;
  15.         blockCollider.SetActive(true);                  //啟用格擋Collider
  16.         animator.SetTrigger("Block");
  17.     }
複製程式碼

(2)BlockCollider上的程式碼(含註釋)如下:

在BlockCollider上新增指令碼,當碰到敵人的武器時,如果玩家是PerfectBlock狀態,使敵人變為BeBlock狀態,觸發彈反,否則玩家進入格擋受擊狀態(isBImpact)。

  1. private void OnTriggerEnter(Collider other)
  2.     {
  3.         if (other.CompareTag("EWeapon"))
  4.         {
  5.             Enemy enemy = other.GetComponentInParent<Enemy>();
  6.             if (!player.isPerfectBlock)
  7.             {
  8.                 player.isBImpact = true;        //格擋受擊
  9.             }
  10.             else
  11.             {
  12.                 enemy.eState = Estate.BeBlock;  //彈反
  13.             }
  14.         }
  15.     }
複製程式碼

結語:實現簡單版彈反的主要功能基本都介紹完了,實質上是Collider與Animator的應用,有興趣的小夥伴可以下載工程看看設定引數或者其他小功能的實現,希望對大家有所啟發。

下載連結:https://pan.baidu.com/s/15kbKX5XUfI5_ZDtZ0xLDVw

提取碼:ok3f

我們們的遊戲開發交流群也歡迎強勢插入:869551769

希望參與線下游戲開發學習的,歡~~~~~~迎訪問:http://levelpp.com/

作者:Truly
專欄地址:https://zhuanlan.zhihu.com/p/81086005

相關文章