用Unity實現彈反效果
大渣好。
老賊的黑魂系列,想必大家都樂(tong)在其中。
那麼要說到魂系列、乃至很多其他ACT要素濃郁的作品,最核心的機制之一,那就是彈反(視遊戲不同叫法也不同,一閃、完美防禦、彈開等等)。
實現了這個效果,(理論上)你也可以做一個類似的遊戲出來(強調:只是理論上,只是理論上)。
今天我們就用簡單粗暴的方法來實現一個彈反。
先看效果圖。
圖中可知:
- 持續格擋,受擊時有晃動、硬直動作。
- 完美格擋成功時(會根據攻擊方向進行格擋),敵人攻擊會被彈開。
- 當敵人被彈開攻擊3次時,會進入後仰慢動作。
這次用的資源是在https://www.mixamo.com裡免費下的Great Sword Pack和Pro Sword And Shield Pack,需要的可以在工程裡邊拉或者自行下載。匯入資源後,用Plane和Cube隨便搭建一個場地。
由於這是一個簡單版的彈反功能實現,因此我們只需要製作兩個功能殘缺的工具人:一個只會左砍右砍的雙刀火雞哥,一個只能跑和防反的大劍姐。
一、雙劍角色
1.功能及動畫狀態機
雙劍角色作為被彈反的工具人,免費包裡沒有演出效果比較好的動畫,最終只好用同一個揮砍動畫(Slash)通過調節應用在三個狀態中(完美符合乞丐版氣息):左砍、右砍(映象)、被彈反(調節播放速度為負),自己有動畫的小夥伴請毫不猶豫地自行替換。
2.實現思路:
(1)在每個動畫快結束的時候執行動畫幀事件,隨機下一個Slash(揮刀)狀態,啟用對應攻擊源,用於判定攻擊方向。
(2)Slash時用動畫幀事件啟用武器上的觸發器。
(3)被彈反的時候,調節播放速度AnimaSpeed為負,使其回放。
(4)當被彈反3次時觸發BehitBack後仰動畫。
3.相關設定
(1)角色設定
以下新增的Collider都勾選IsTrigger。
①給角色新增CapsuleCollider,然後調節至跟角色差不多大小。
②新增RigidBody,並勾選IsKinematic。
③展開角色的骨骼,分別給雙劍所在節點加上BoxCollier元件,並且調節至跟劍差不多大小,設定Tag為”EWeapon”,用於格擋時碰撞檢測。
④在劍的節點下邊新建一個空的物體SwordOri並新增Collider元件,設定Tag”為EWeaponOri”,作為攻擊源用於給玩家判定攻擊方向。
(2)設定動畫
因為需要一個後仰的慢動作,把BehitBack動畫的Speed調為0.5。
4.部分功能實現
(1)啟用武器的Collider
- 雙擊Animator視窗裡的LSlash,展開Events,拖動動畫進度條。
- 在手剛揮到角色前方的位置,點選Events下“+”,新增動畫幀事件(當動畫播放到這個位置時會執行對應名稱的方法),設定完成後Apply。
由於LSlash和RSlash使用的是同一個動畫,這裡通過獲取當前動畫狀態的名字的方式來判斷應該啟用哪邊的武器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;
- }
- }
同理,在砍動作結束時新增動畫幀事件關閉武器的Collider。
(2)被彈反
這次乞丐版的彈反實際上是Slash動畫的回放,所以只要播放速度為負即可,為了提升視覺效果,我們通過動畫曲線模擬先快後慢的彈開速度。
①設定動畫曲線
在指令碼中宣告一個變數public AnimationCurve animaSpeed,儲存後我們可以在Unity中找到這個變數,點選右側圖框便能編輯曲線。
橫軸將作為時間,豎軸將作為播放速度(具體引數按自己喜好調節):
②根據動畫曲線調節播放速度
- 開啟Animator視窗,新增float型別引數AnimaSpeed。
- 找到LSlash和RSlash兩個動畫狀態,分別勾選Speed下Multiplier的Parameter並選擇AnimSpeed,把動畫播放的速度與引數AnimaSpeed建立聯絡。
- 通過AnimationCurve.Evaluate(float time)設定AnimaSpeed來調節播放速度。
程式碼(含註釋)如下:
- //被格擋時觸發動作回彈
- public IEnumerator BeBlocked()
- {
- OnAnimation_CloseWeaponCollier(); //關閉武器碰撞盒
- beBlock = true;
- beBlockCounter += 1; //被彈反次數+1
- timer = 0;
- while (timer < 0.8f) //彈反動畫播放0.8s
- {
- SetAnimaSpeed();
- yield return new WaitForFixedUpdate();
- }
- beBlock = false;
- OnAnimation_RandomAState(); //隨機下一個狀態
- animator.SetFloat("AnimaSpeed", 1); //播放速度恢復正常
- }
- //設定格擋回彈時的速度
- public void SetAnimaSpeed()
- {
- timer += Time.fixedDeltaTime; //計時
- animaSpeed = animaSpeedCur.Evaluate(timer); //讀取曲線資料
- animator.SetFloat("AnimaSpeed", animaSpeed); //設定播放速度
- }
二、大劍角色
1.功能及動畫狀態機
大劍角色具有隻有格擋(完美格擋、持續格擋、受擊)和移動功能。
2.實現思路:
(1)點選右鍵,進入PerfectBlock狀態,根據敵人攻擊來方觸發對應的格擋動畫。
(2)當在PerfectBlock狀態下,敵人的武器碰到格擋Collider時會被彈反。
(3)按住右鍵進入KeepBlocking狀態,持續防禦。
(4)當在KeepBlocking狀態下,敵人的武器碰到格擋Collider時,玩家被擊晃動。
3.相關設定
(1)角色設定
以下新增的Collider都勾選IsTrigger。
①給角色新增Character Controller元件,用於實現移動。
②新增BoxCollider,調節大小與位置,使其位於角色前方,用於探測敵人和判定攻擊方向。
③展開角色骨骼,在武器節點下新建空的子物體BlockCollider並新增BoxCollider,用於格擋檢測,可以適量調大來增加格擋容錯率。
(2)動畫設定
當只有左方向的格擋動畫時,可以通過設定動畫狀態的Mirror(映象)屬性獲得右方向的格擋動畫。
拿PerfectBlock作為例子,在Animator新增一個Bool型別引數isRightB,在Inspector視窗如下圖設定:勾選Mirror右側Parameter,並選擇引數isRightB,表示當isRightB為true時播放映象。接下來只需在指令碼中控制isRightB的切換就可以控制左右格擋。
剩下的KeepBlock、BlockImpact、BlockEnd狀態也這樣操作,就可以獲得一套右格擋動畫。
4.部分功能實現
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進行碰撞監測,並且根據攻擊來向播放相應的格擋動畫。
- //格擋
- public void Block()
- {
- if (isFighting) //如果戰鬥相關動畫在播放,則返回
- {
- return;
- }
- if (eWeaponOriTrans) //如果檢測到敵人攻擊源
- {
- CheckAttackDir(eWeaponOriTrans.position); //檢測敵人攻擊方向
- }
- LookAtTarget(); //轉向目標
- isBlocking = true;
- isPerfectBlock = true;
- blockCollider.SetActive(true); //啟用格擋Collider
- animator.SetTrigger("Block");
- }
(2)BlockCollider上的程式碼(含註釋)如下:
在BlockCollider上新增指令碼,當碰到敵人的武器時,如果玩家是PerfectBlock狀態,使敵人變為BeBlock狀態,觸發彈反,否則玩家進入格擋受擊狀態(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; //彈反
- }
- }
- }
結語:實現簡單版彈反的主要功能基本都介紹完了,實質上是Collider與Animator的應用,有興趣的小夥伴可以下載工程看看設定引數或者其他小功能的實現,希望對大家有所啟發。
下載連結:https://pan.baidu.com/s/15kbKX5XUfI5_ZDtZ0xLDVw
提取碼:ok3f
我們們的遊戲開發交流群也歡迎強勢插入:869551769
希望參與線下游戲開發學習的,歡~~~~~~迎訪問:http://levelpp.com/
作者:Truly
專欄地址:https://zhuanlan.zhihu.com/p/81086005
相關文章
- Android中ScrollView實現拖拽反彈效果動畫AndroidView動畫
- Flutter 實現虎牙/鬥魚 彈幕效果Flutter
- Unity實現“籠中窺夢”的渲染效果Unity
- Unity使用DOTween實現金幣飛入效果Unity
- js 反斜槓\實現折行效果JS
- Unity——ShaderLab實現玻璃和鏡子效果Unity
- Unity Shader 實現雨天的水面漣漪效果Unity
- js實現彈出層滑鼠跟隨效果JS
- jquery實現的彈出居中視窗效果jQuery
- Android彈幕功能實現,模仿鬥魚直播的彈幕效果Android
- 使用Unity著色器實現精靈(Sprite)塗鴉效果Unity
- unity 實現輪盤方式的按鈕滾動效果Unity
- Unity遊戲開發技巧集錦2.1.3實現效果Unity遊戲開發
- SpringAnimator彈簧聯動效果的實現Spring
- JS實現彈幕效果(10.11—10.17)JS
- SVG 動畫實現彈性的頁面元素效果SVG動畫
- Android實現人人網點選“+”彈出效果Android
- CSS3實現的頁面反轉效果CSSS3
- 原生 js 實現移動端 Touch 滑動反彈JS
- canvas實現的彈力小球效果程式碼例項Canvas
- 使用canvas實現一個圓球的觸壁反彈Canvas
- 原生js實現一個DIV的碰撞反彈運動JS
- 用css實現視差效果CSS
- 用JavaScript實現動畫效果 (轉)JavaScript動畫
- Unity5 PBR如何實現天氣系統的雪景效果Unity
- 奉獻一個實用的JS動畫彈出層效果JS動畫
- 登入頁Activity從下向上的彈出效果實現
- jQuery實現的點選彈出登陸視窗效果jQuery
- Path實現常見toolbar點選彈出選單效果
- js實現checkbox核取方塊的反選效果JS
- 藉助XPopup,用50行程式碼實現更好的抖音評論彈窗效果!行程
- 用純 CSS 實現鏤空效果CSS
- Unity 高清渲染管線 ShaderGraph 實現簡單的表面水流效果Unity
- Unity3D中暫停時的動畫及粒子效果實現Unity3D動畫
- 用javascript實現全選/反選元件JavaScript元件
- 如何不使用js實現滑鼠hover彈出選單效果JS
- jQuery實現的自定義可以拖動的彈出層效果jQuery
- css實現的彈出視窗始終垂直水平居中效果CSS