­

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片段。邏輯正常
    • 此後整體動畫全權由attack_2運轉
  • 情況二:當attack_1正常運轉,在左邊標記後(左右標記中或是右標記後)達成轉換條件
    • 立即開啟Translation和attack_2,三者並行運轉
      • 若Translation還在運行中,attack_1卻先運行完,代表當前動畫片attack_2運行完,結果同上
      • 若attack_1還在運行中,Translation卻先運行完,則立即停止attack_2片段。邏輯正常
    • 此後整體動畫全權由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片段。邏輯正常
    • 此時整體動畫全權由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

Translation後於Animation錯誤問題:

該錯誤直觀上看就是兩動畫和Translation時間先後問題,數字上看就是Translation首尾點、區間大小、條件達成時機。因此解決辦法就圍繞這幾點,此處給出幾點建議:

  • Translation右標記最好 <= 前Animation末端,也就是說Translation不要超齣動畫長度
  • 最好在左標記點前達成轉換條件,以便我們對轉換過程進行掌控
  • AnimatorController的設置不是唯一途徑,程式碼操控、動畫內插入事件等,都可以較好輔助我們實現安全的動畫切換

參考