用Unity實現(xiàn)彈反效果

作者:Truly
大渣好。
老賊的黑魂系列,想必大家都樂(tong)在其中。

那么要說到魂系列、乃至很多其他ACT要素濃郁的作品,最核心的機制之一,那就是彈反(視游戲不同叫法也不同,一閃、完美防御、彈開等等)。
實現(xiàn)了這個效果,(理論上)你也可以做一個類似的游戲出來(強調(diào):只是理論上,只是理論上)。
今天我們就用簡單粗暴的方法來實現(xiàn)一個彈反。
先看效果圖。

圖中可知:
持續(xù)格擋,受擊時有晃動、硬直動作。
完美格擋成功時(會根據(jù)攻擊方向進行格擋),敵人攻擊會被彈開。
當敵人被彈開攻擊3次時,會進入后仰慢動作。
這次用的資源是在:https://www.mixamo.com?里免費下的Great Sword Pack和Pro Sword And Shield Pack,需要的可以在工程里邊拉或者自行下載。導入資源后,用Plane和Cube隨便搭建一個場地。
由于這是一個簡單版的彈反功能實現(xiàn),因此我們只需要制作兩個功能殘缺的工具人:一個只會左砍右砍的雙刀火雞哥,一個只能跑和防反的大劍姐。
一、雙劍角色
1.功能及動畫狀態(tài)機
雙劍角色作為被彈反的工具人,免費包里沒有演出效果比較好的動畫,最終只好用同一個揮砍動畫(Slash)通過調(diào)節(jié)應用在三個狀態(tài)中(完美符合乞丐版氣息):左砍、右砍(鏡像)、被彈反(調(diào)節(jié)播放速度為負),自己有動畫的小伙伴請毫不猶豫地自行替換。

2.實現(xiàn)思路:
(1)在每個動畫快結(jié)束的時候執(zhí)行動畫幀事件,隨機下一個Slash(揮刀)狀態(tài),激活對應攻擊源,用于判定攻擊方向。
(2)Slash時用動畫幀事件激活武器上的觸發(fā)器。
(3)被彈反的時候,調(diào)節(jié)播放速度AnimaSpeed為負,使其回放。
(4)當被彈反3次時觸發(fā)BehitBack后仰動畫。
3.相關設置
(1)角色設置
以下添加的Collider都勾選IsTrigger。
①給角色添加CapsuleCollider,然后調(diào)節(jié)至跟角色差不多大小。

②添加RigidBody,并勾選IsKinematic。
③展開角色的骨骼,分別給雙劍所在節(jié)點加上BoxCollier組件,并且調(diào)節(jié)至跟劍差不多大小,設置Tag為”EWeapon”,用于格擋時碰撞檢測。
④在劍的節(jié)點下邊新建一個空的物體SwordOri并添加Collider組件,設置Tag”為EWeaponOri”,作為攻擊源用于給玩家判定攻擊方向。

(2)設置動畫
因為需要一個后仰的慢動作,把BehitBack動畫的Speed調(diào)為0.5。

4.部分功能實現(xiàn)
(1)激活武器的Collider
雙擊Animator窗口里的LSlash,展開Events,拖動動畫進度條。
在手剛揮到角色前方的位置,點擊Events下“+”,添加動畫幀事件(當動畫播放到這個位置時會執(zhí)行對應名稱的方法),設置完成后Apply。

由于LSlash和RSlash使用的是同一個動畫,這里通過獲取當前動畫狀態(tài)的名字的方式來判斷應該激活哪邊的武器Collider,代碼(含注釋)如下:
//激活武器Collider
??? public void OnAnimation_OpenSwordCollider()
??? {
??????? if (beBlock)
??????? {
??????????? return;
??????? }
??????? //獲取當前動畫信息
??????? aniInfo = animator.GetCurrentAnimatorStateInfo(0);
?
??????? if (aniInfo.IsName("LSlash"))?????? //激活左劍Collider
??????? {
??????????? lSwordCollider.enabled = true;?
??????? }
??????? else if (aniInfo.IsName("RSlash"))? //激活右劍Collider
??????? {
??????????? rSwordCollider.enabled = true;
??????? }
??? }
?
同理,在砍動作結(jié)束時添加動畫幀事件關閉武器的Collider。
(2)被彈反
這次乞丐版的彈反實際上是Slash動畫的回放,所以只要播放速度為負即可,為了提升視覺效果,我們通過動畫曲線模擬先快后慢的彈開速度。
①設置動畫曲線
在腳本中聲明一個變量public?AnimationCurve?animaSpeed,保存后我們可以在Unity中找到這個變量,點擊右側(cè)圖框便能編輯曲線。

橫軸將作為時間,豎軸將作為播放速度(具體參數(shù)按自己喜好調(diào)節(jié)):

②根據(jù)動畫曲線調(diào)節(jié)播放速度
打開Animator窗口,添加float類型參數(shù)AnimaSpeed。
找到LSlash和RSlash兩個動畫狀態(tài),分別勾選Speed下Multiplier的Parameter并選擇AnimSpeed,把動畫播放的速度與參數(shù)AnimaSpeed建立聯(lián)系。
通過AnimationCurve.Evaluate(float time)設置AnimaSpeed來調(diào)節(jié)播放速度。

代碼(含注釋)如下:
//被格擋時觸發(fā)動作回彈
??? public IEnumerator BeBlocked()
??? {
??????? OnAnimation_CloseWeaponCollier();?????? //關閉武器碰撞盒
??????? beBlock = true;????????????????????????
??????? beBlockCounter += 1;??????????????????? //被彈反次數(shù)+1
??????? timer = 0;
??????? while (timer < 0.8f)??????????????????? //彈反動畫播放0.8s
???? ???{
??????????? SetAnimaSpeed();
??????????? yield return new WaitForFixedUpdate();
??????? }
??????? beBlock = false;
??????? OnAnimation_RandomAState();???????????? //隨機下一個狀態(tài)
??????? animator.SetFloat("AnimaSpeed", 1);???? //播放速度恢復正常
??? }
?
??? //設置格擋回彈時的速度
??? public void SetAnimaSpeed()
??? {??????
??????? timer += Time.fixedDeltaTime;?????????????????? //計時
??????? animaSpeed = animaSpeedCur.Evaluate(timer);???? //讀取曲線數(shù)據(jù)
??????? animator.SetFloat("AnimaSpeed", animaSpeed);??? //設置播放速度
??? }
?
二、大劍角色
1.功能及動畫狀態(tài)機
大劍角色具有只有格擋(完美格擋、持續(xù)格擋、受擊)和移動功能。

2.實現(xiàn)思路:
(1)點擊右鍵,進入PerfectBlock狀態(tài),根據(jù)敵人攻擊來方觸發(fā)對應的格擋動畫。
(2)當在PerfectBlock狀態(tài)下,敵人的武器碰到格擋Collider時會被彈反。
(3)按住右鍵進入KeepBlocking狀態(tài),持續(xù)防御。
(4)當在KeepBlocking狀態(tài)下,敵人的武器碰到格擋Collider時,玩家被擊晃動。
3.相關設置
(1)角色設置
以下添加的Collider都勾選IsTrigger。
①給角色添加Character Controller組件,用于實現(xiàn)移動。
②添加BoxCollider,調(diào)節(jié)大小與位置,使其位于角色前方,用于探測敵人和判定攻擊方向。
③展開角色骨骼,在武器節(jié)點下新建空的子物體BlockCollider并添加BoxCollider,用于格擋檢測,可以適量調(diào)大來增加格擋容錯率。


(2)動畫設置
當只有左方向的格擋動畫時,可以通過設置動畫狀態(tài)的Mirror(鏡像)屬性獲得右方向的格擋動畫。
拿PerfectBlock作為例子,在Animator添加一個Bool類型參數(shù)isRightB,在Inspector窗口如下圖設置:勾選Mirror右側(cè)Parameter,并選擇參數(shù)isRightB,表示當isRightB為true時播放鏡像。接下來只需在腳本中控制isRightB的切換就可以控制左右格擋。

剩下的KeepBlock、BlockImpact、BlockEnd狀態(tài)也這樣操作,就可以獲得一套右格擋動畫。
4.部分功能實現(xiàn)
Block
(1)角色上的代碼(含注釋)如下:
①敵人攻擊時,大劍角色前方的大Collider會檢測到敵人的SwordOri。
private void OnTriggerEnter(Collider other)
??? {
??????? if (other.CompareTag("Enemy"))????????????????? //獲取敵人Transform
??????? {
??????????? targetTrans = other.transform;
??????? }
?
??????? if (other.CompareTag("EWeaponOri"))???????????? //檢測敵人攻擊時激活的攻擊源Collider
??????? {
??????????? eWeaponOriTrans = other.transform;
??????? }
??? }
?
②敵人攻擊時會激活SwordOri,通過計算SwordOri與角色右方的夾角,決定格擋方向。

//檢測攻擊方向
??? void CheckAttackDir(Vector3 eWeaponOriPos)
??? {
??????? Vector3 aDir = eWeaponOriPos - transform.position;????? //從玩家指向敵人攻擊源
??????? float angle = Vector3.Angle(transform.right, aDir);???? //計算aDir與角色右方的夾角
??????? if (angle < 90)???????????????????????????????????????? //夾角<90度往右格擋
??????? {
??????????? isRightB = true;???????????????????????????????????
??????? }
??????? else
??????? {
???????? ???isRightB = false;?????????????????????????????????? //否則往左格擋
??????? }
??? }
?
③激活blockCollider進行碰撞監(jiān)測,并且根據(jù)攻擊來向播放相應的格擋動畫。
//格擋
??? public void Block()
??? {
??????? if (isFighting)???????????????????????????????? //如果戰(zhàn)斗相關動畫在播放,則返回
??????? {
??????????? return;
??????? }
?
??????? if (eWeaponOriTrans)??????????????????????????? //如果檢測到敵人攻擊源
??????? {
??????????? CheckAttackDir(eWeaponOriTrans.position);?? //檢測敵人攻擊方向
??????? }
?
??????? LookAtTarget();???????????????????????????????? //轉(zhuǎn)向目標
??????? isBlocking = true;
??????? isPerfectBlock = true;
??? ????blockCollider.SetActive(true);????????????????? //激活格擋Collider
??????? animator.SetTrigger("Block");
??? }
?
(2)BlockCollider上的代碼(含注釋)如下:
在BlockCollider上添加腳本,當碰到敵人的武器時,如果玩家是PerfectBlock狀態(tài),使敵人變?yōu)锽eBlock狀態(tài),觸發(fā)彈反,否則玩家進入格擋受擊狀態(tài)(isBImpact)。
private void OnTriggerEnter(Collider other)
??? {
??????? if (other.CompareTag("EWeapon"))
??????? {
??????????? Enemy enemy = other.GetComponentInParent<Enemy>();
??????????? if (!player.isPerfectBlock)
??????????? {
??????????????? player.isBImpact = true;??????? //格擋受擊
??????????? }
??????????? else
??????????? {
??????????????? enemy.eState = Estate.BeBlock;? //彈反
??????????? }
??? ????}
??? }
?
結(jié)語:實現(xiàn)簡單版彈反的主要功能基本都介紹完了,實質(zhì)上是Collider與Animator的應用,有興趣的小伙伴可以下載工程看看設置參數(shù)或者其他小功能的實現(xiàn),希望對大家有所啟發(fā)。
下載鏈接:https://pan.baidu.com/share/init?surl=5kbKX5XUfI5_ZDtZ0xLDVw
提取碼:ok3f
咱們的游戲開發(fā)交流群也歡迎強勢插入:869551769
希望參與線下游戲開發(fā)學習的,歡~~~~~~迎訪問:http://www.levelpp.com/