1. 程式人生 > >Unity3D開發之設定Animator播放動畫片段結束後事件設定

Unity3D開發之設定Animator播放動畫片段結束後事件設定

最近專案需求做一個效果動畫,在unity自己編輯的關於Transfrom+Color Alpha變化的動畫。動畫編輯好後在Animator面板編輯動畫切換條件。初始狀態,動畫進入一個空狀態,當我們要展示效果的時候,就設定他的引數值Score=True,讓他切換動畫。切換完後再切回空狀態並設定Score為false。如下圖:

剛開始我一直在過度條件面板以及動畫狀態面板尋找可以新增的事件。但是並沒有,百度也是搜到一些程式碼監控狀態機動畫播放是否結束。我覺得那個有點麻煩,不太符合我的需求。在我記憶裡這個應該是可以更簡單的實現。果然,在我不斷嘗試下終於找到了解決方法。我們點選狀態時,會發現一個Add Behaviour。

我嘗試Add一個新的指令碼開啟後發現這正是可以用來監聽當前動畫狀態一些事件的一些函式。如下:

public class ParaSetting : StateMachineBehaviour {

    // OnStateEnter is called when a transition starts and the state machine starts to evaluate this state
    //override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) {
    //
    //}

    // OnStateUpdate is called on each Update frame between OnStateEnter and OnStateExit callbacks
    //override public void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) {
    //
    //}

    // OnStateExit is called when a transition ends and the state machine finishes evaluating this state
    override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
    {
        animator.SetBool("Score",false);
    }

    // OnStateMove is called right after Animator.OnAnimatorMove(). Code that processes and affects root motion should be implemented here
    //override public void OnStateMove(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) {
    //
    //}

    // OnStateIK is called right after Animator.OnAnimatorIK(). Code that sets up animation IK (inverse kinematics) should be implemented here.
    //override public void OnStateIK(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) {
    //
    //}
}

這樣我們就可以在狀態機裡新增一些動畫完成狀態後的響應了。

順便記錄一下查到的獲取到當前動畫時長程式碼如下:

 public static float GetClipLength(this Animator animator, string clip)
    {
        if (null == animator || string.IsNullOrEmpty(clip) || null == animator.runtimeAnimatorController)
            return 0;
        RuntimeAnimatorController ac = animator.runtimeAnimatorController;
        AnimationClip[] tAnimationClips = ac.animationClips;
        if (null == tAnimationClips || tAnimationClips.Length <= 0) return 0;
        AnimationClip tAnimationClip;
        for (int tCounter = 0, tLen = tAnimationClips.Length; tCounter < tLen; tCounter++)
        {
            tAnimationClip = ac.animationClips[tCounter];
            if (null != tAnimationClip && tAnimationClip.name == clip)
                return tAnimationClip.length;
        }
        return 0F;
    }

動畫是否播放完畢:

public static bool PlayWasOver(this Animator animator)
    {
        AnimatorStateInfo info = animator.GetCurrentAnimatorStateInfo(0);
        if (info.normalizedTime >= 1.0f) return true;
        else return false;
    }