1. 程式人生 > >Unity - HasExitTime用法

Unity - HasExitTime用法

本文詳細分析了AnimatorController中動畫切換過渡問題,即Translation過渡及hasExitTime的問題。方法為對實際專案中的所有情況進行分類,規劃邏輯圖,視覺化分析解決這些問題。

  • 部落格園:Unity HasExitTime用法 - SouthBegonia
  • 專案地址:Hero - SouthBegonia

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的設定不是唯一途徑,程式碼操控、動畫內插入事件等,都可以較好輔助我們實現安全的動畫切換

參考

  • Unity5.X 從入門到精通 - UnityTechnologies
  • Unity2D實現人物三連擊 - 逐影
  • Unity3d基礎:Animator動畫三連擊 - 考班格
  • Unity遊戲動畫 從入門到住院:動畫機狀態 - GameRes