【Unity】Animatorの終了検知


コーディング作業

Animatorを使用したAnimationの終了を検知する方法を記載します。

Animatorについて

公式では以下のように説明されています。

Mecanim のアニメーションシステムをコントロールするためのインターフェースです。

https://docs.unity3d.com/jp/current/ScriptReference/Animator.html

Unityで3Dをアニメーションするための仕組みで、それを制御するための機能だという意味です。

以下は私の追加補足です。

UnityのGameObjectにアタッチ(追加)するCompornentで、アニメーションの情報を保存したAnimationを管理するものです。

AnimatorはTriggerやFlagがあり、それに応じて動作するAnimationを切り替えます。
Animatorに設定した情報はAnimatorControllerに保存されます。

  • Animator:アニメーションを管理するツール
  • Animation:アニメーションを保存したデータ
  • AnimatorController:Animator設定を保存したデータ

Animatorで終了検知

サンプル

サンプルとしてアプリのタブの動作を作りました。
処理の流れを確認するためにAnimationの秒数を遅くしているため、動作が遅く見えます。

  1. タブのボタンが押される
  2. タブのレイアウトが開く
  3. タブのボタンの色が変わる

Animatorの説明

Animatorは以下のようになっています。
Animation同士が矢印で繋がっており、矢印の方向のAnimationにのみ切り替わることができます。
この切り替わりをStateの変更といいます。
※どこからでもStateを変更にはAny Stateから矢印を伸ばす。

  • 起動時はDefaultが呼ばれます。
    • 空のAnimationなので何も起こりません。
  • Defaultからは以下の3つにStateを変更できます。
    • OpenTab1Anim:タブ1が開く
    • OpenTab2Anim:タブ2が開く
    • OpenTab3Anim:タブ3が開く
  • タブが開いた状態の時、タブを閉じることができます。
    • OpenTab1Anim → CloseTab1Anim
    • タブが閉じると自動でDefaultに戻ります。

制御するScript

以下のScriptでタブのボタンが押されたときにAnimatorへのTriggerを送っています。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TabScript : MonoBehaviour {

    public UnityEngine.UI.Image Tab1Button;
    public UnityEngine.UI.Image Tab2Button;
    public UnityEngine.UI.Image Tab3Button;

    public Animator TabAnimController;

    /*======================================================*
     * Default Method
     *======================================================*/
    // Use this for initialization
    void Start () {
        Tab1Button.color = new Color32 (180, 230, 255, 255);
        Tab2Button.color = new Color32 (180, 230, 255, 255);
        Tab3Button.color = new Color32 (180, 230, 255, 255);
    }

    // Update is called once per frame
    void Update () {

    }

    /*======================================================*
     * Button Action Method
     *======================================================*/
    //タブ1が押された
    public void Tab1ButtonTapped () {
        StartCoroutine ("Tab1Animation");
    }

    //タブ2とタブ3が押された時の処理は
    //Tab1Animation()と同じ作りのメソッドをTab2,Tab3用に作成。
    //Tab1ButtonTapped()と同じくコルーチンで呼び出すだけなので省略します。

    /*======================================================*
     * Animation Method
     *======================================================*/
    //タブ1を開閉するアニメーション
    private IEnumerator Tab1Animation() {
        AnimatorStateInfo stateInfo = TabAnimController.GetCurrentAnimatorStateInfo(0);
        if (stateInfo.IsName ("OpenTab1Anim")) {
            //タブ1→Default
            TabAnimController.SetTrigger ("CloseTab1Anim");
            //タブボタン変更
            var closeCoroutine = StartCoroutine("WaitAnimationEnd","CloseTab1Anim");
            yield return closeCoroutine;
            Tab1Button.color = new Color32 (180, 230, 255, 255);
        } else {
            if (stateInfo.IsName ("Default")) {
                //Default→タブ1
                TabAnimController.SetTrigger ("OpenTab1Anim");
            } else {
                if (stateInfo.IsName("OpenTab2Anim")) {
                    //タブ2→タブ1
                    TabAnimController.SetTrigger("CloseTab2Anim");
                    var closeCoroutine = StartCoroutine("WaitAnimationEnd","CloseTab2Anim");
                    yield return closeCoroutine;
                    TabAnimController.SetTrigger ("OpenTab1Anim");
                    Tab2Button.color = new Color32 (180, 230, 255, 255);
                } else if (stateInfo.IsName("OpenTab3TabAnim")) {
                    //タブ3→タブ1
                    TabAnimController.SetTrigger("CloseTab3Anim");
                    var closeCoroutine = StartCoroutine("WaitAnimationEnd","CloseTab3Anim");
                    yield return closeCoroutine;
                    TabAnimController.SetTrigger ("OpenTab1Anim");
                    Tab3Button.color = new Color32 (180, 230, 255, 255);
                }
            }
            //タブボタン変更
            var openCoroutine = StartCoroutine("WaitAnimationEnd","OpenTab1Anim");
            yield return openCoroutine;
            Tab1Button.color = new Color32 (73, 194, 255, 255);
        }
    }

    //アニメーション終了を判定するコルーチン
    private IEnumerator WaitAnimationEnd(string animatorName) {
        bool finish = false;
        while (!finish) {
            AnimatorStateInfo nowState = TabAnimController.GetCurrentAnimatorStateInfo(0);
            if (nowState.IsName (animatorName)) {
                finish = true;
            } else {
                yield return new WaitForSeconds (0.1f);
            }
        }
    }
}

重要なのはAnimatorから取得しているAnimationStateInfoです。

AnimatorStateInfo stateInfo = TabAnimController.GetCurrentAnimatorStateInfo(0);

AnimatorStateInfoはAnimationの情報です。
アニメーションの長さだったり、名前を取得できます。
GetCurrentAnimatorStateInfo()は現在Animatorで止まっているStateのAnimationを取得するメソッドです。
引数の0はAnimatorのLayersの何番目かを表しています。 通常は0です。

stateInfo.IsName ("Default")

AnimatorStateInfoで取得したStateがどのAnimationなのかを判別します。
ここではDefaultのAnimationはタブを閉じている状態なので、タブが閉じていればtrueを返します。

TabAnimController.SetTrigger ("OpenTab1Anim");

Animatorのトリガーを呼んでいます。
OpenTab1Animのトリガーを呼ぶことでタブ1が開くアニメーションが開始します。
CloseTab1Animの場合は閉じます。

WaitAnimationEnd(string animatorName)

アニメーションが終了するのを検知するためのメソッドです。
内部では0.1秒ごとにIsName()を使ってアニメーションの終了を確認しています。

Leave a Comment

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です