Unity – HasExitTime用法
- 2019 年 10 月 27 日
- 筆記
本文詳細分析了AnimatorController中動畫切換過渡問題,即Translation過渡及hasExitTime的問題。方法為對實際項目中的所有情況進行分類,規劃邏輯圖,可視化分析解決這些問題。
AnimatorController 動畫機控制器
- 功能:對已有的Animation片進行邏輯連接,連接過渡方式為Translation有向線段,其切換方法包括啟用hasExitTime和關閉hasExitTime
- Translation:通過設置Parameters的參數進行切換過渡,可單線上有多條件,也可單方向上有多單條件線。選中任意Translation可在Inspecter窗口看到兩個動畫片段和區間的窗口,及Setting參數表
- hasExitTime:是否有退出時間。簡單理解:開啟表示等待當前動畫進行完才可進行下一個動畫;關閉表示可以立即打斷當前動畫並播放下一個動畫
項目實戰
- 背景:存在idle、idle_2、attack_1、attack_2、attack_3動畫片段實現三連擊的攻擊效果,根據attack值切換。我們僅關注幾個attack的切換,其中
- attack_1->attack_2:關閉hasExitTime,切換條件attack=2,Translation未超
- attack_2->attack_3:開啟hasExitTime,切換條件attack=3,Translation未超
- attack_1、attack_2、attack_3切換到idle_2:切換條件attack=0,程式碼控制判斷任意動畫播放完畢則attack=0
AnimatorController:
attack_1->attack_2(左)、attack_2->attack_3(右)的Translation:
1. 關閉 has exit time
關閉has Exit Time:無退出等待時間,立即開啟下一動畫
- 情況一:當attack_1正常運轉,在左標記前達成轉行條件
- 立即開啟Translation(而不是等待運行到左標記)和attack_2,三者並行運轉
- 若Translation還在運行中,attack_1卻先運行完,代表當前動畫片attack_1運行完(程式碼:
(stateInfo.IsName("attack_1") && stateInfo.normalizedTime > 1)) == true
),會對邏輯上的判斷造成影響,這種情況非常容易出錯 - 若attack_1還在運行,Translation卻先運行完,則立即停止attack_1片段。邏輯正常
- 若Translation還在運行中,attack_1卻先運行完,代表當前動畫片attack_1運行完(程式碼:
- 此後整體動畫全權由attack_2運轉
- 立即開啟Translation(而不是等待運行到左標記)和attack_2,三者並行運轉
- 情況二:當attack_1正常運轉,在左邊標記後(左右標記中或是右標記後)達成轉換條件
- 立即開啟Translation和attack_2,三者並行運轉
- 若Translation還在運行中,attack_1卻先運行完,代表當前動畫片attack_2運行完,結果同上
- 若attack_1還在運行中,Translation卻先運行完,則立即停止attack_2片段。邏輯正常
- 此後整體動畫全權由attack_2運轉
- 立即開啟Translation和attack_2,三者並行運轉
邏輯圖:(修正:count=0 表示attack=0)
項目實例圖:左標前達成(先),左標後達成且Translation後完成(後)
2. 開啟 has exit time
當has exit time:有退出等待時間,需等待目前動畫完成到一定階段才可切換至下一動畫。過程:
- 情況一:attack_2正常運轉,若在左標記前達成轉換條件
- 等待attack_2中動畫片進行到左標記,開啟Translation過渡和attack_3動畫,,三者動畫並行運轉
- 若Translation還在運行中,attack_2卻先運行完,代表當前動畫片attack_2運行完(程式碼:
(stateInfo.IsName("attack_1") && stateInfo.normalizedTime > 1)) == true
),會對邏輯上的判斷造成影響,這種情況非常容易出錯 - 若attack_2還在運行,Translation卻先運行完,則立即停止attack_2片段。邏輯正常
- 若Translation還在運行中,attack_2卻先運行完,代表當前動畫片attack_2運行完(程式碼:
- 此時整體動畫全權由attack_3運轉;
- 等待attack_2中動畫片進行到左標記,開啟Translation過渡和attack_3動畫,,三者動畫並行運轉
- 情況二:attack_2正常運轉,若在左標記後達成條件
- 無論是在標記期間或是右標記後達成條件,再也無法觸發Translation轉換,因為可過渡時間片已經錯過了
邏輯圖:(修正:count=0 表示attack=0)
項目實例圖:左標前達成(先),左標後達成(後)
總結
Translation內左右標記問題:
- 左右標記範圍含義:
- Translation時長,兩個動畫的過渡時間長度
- 左右標記位置含義:
- 對於當前Animation:左標記表示開啟Translation和下一Animation的時間點;右標記表示當前動畫片所能進行到的最晚時間點
- 對於下一Animation:左標記為當前動畫開啟時間點,右標記為當前動畫全權運轉時間點
- 通俗解釋:何時轉換、轉換多久、轉換時兩動畫所佔比例
- 區間意義:
- 例如attack_1和attack_2過渡的時間片段,過渡期的動畫由Unity根據attack_1和attack_2動畫混合而成,因此所謂三動畫並行執行,本質為執行Translation的混合動畫。其外需要注意:過渡期間仍處於attack_1,程式碼就是:
stateInfo.IsName("attack_1")==true
,僅當Translation結束才算處於attack_2
- 例如attack_1和attack_2過渡的時間片段,過渡期的動畫由Unity根據attack_1和attack_2動畫混合而成,因此所謂三動畫並行執行,本質為執行Translation的混合動畫。其外需要注意:過渡期間仍處於attack_1,程式碼就是:
Translation後於Animation錯誤問題:
該錯誤直觀上看就是兩動畫和Translation時間先後問題,數字上看就是Translation首尾點、區間大小、條件達成時機。因此解決辦法就圍繞這幾點,此處給出幾點建議:
- Translation右標記最好 <= 前Animation末端,也就是說Translation不要超齣動畫長度
- 最好在左標記點前達成轉換條件,以便我們對轉換過程進行掌控
- AnimatorController的設置不是唯一途徑,程式碼操控、動畫內插入事件等,都可以較好輔助我們實現安全的動畫切換
參考
- Unity5.X 從入門到精通 – UnityTechnologies
- Unity2D實現人物三連擊 – 逐影
- Unity3d基礎:Animator動畫三連擊 – 考班格
- Unity遊戲動畫 從入門到住院:動畫機狀態 – GameRes