【Unity】アニメーション終了時にメソッドを呼び出す

AnimationClip が終了したときにコールバックを受け取る方法の紹介です。

終了検知を Update メソッドで normalizedTime が 1 になるのを監視する方法がよく紹介されていますので、ここではそれとは違う実現方法を紹介したいと思います。今はアーカイブされてしまいましたが AnimationClip は SimpleAnimation を使用して動作確認を行います。

確認環境

  • Unity 2020.3.2f1

特にどの環境でも問題ないと思いますが確認環境は以下の通りです。

  • Windows10
  • VisualStudio2019

やりかた

まずは準備から行います。SimpleAnimation は既にプロジェクトに導入済みとします。

SimpleAnimation と AnimationClip の準備

まず適当なゲームオブジェクトにに SimpleAnimation をアタッチします。以下の画像は Sprite という SpriteRenderer にSimpleAnimation を追加しています。

次に AnimationClip を作成してSimpleAnimation に追加します。

以下のメニューから Animation を作成します。こうすると AnimationClip が作成できます。

次に作成したアニメーションに「Sample」という名前を付けたので SimpleAnimation に追加します。以下のようにドラッグして名前を付けます。

AnimationClipに適当にアニメーションを設定しておきます。SimpleAnimation が追加されたゲームオブジェクトは Animation タブ(Window > Animation > Animaton から表示できるウインドウ)が有効になるので録画ボタンを押してアニメーションを記録します。

AnimationClip にイベントを追加する

AnimationClip に AddEvent を追加します。以下画像の通り赤枠のボタンを押すとイベントのトリガーを AnimationClip に追加できます。

この縦の線はマウスで左右にドラッグでき、任意の時間にを指定できるのでアニメーションが終了したところまでドラッグして移動します。追加したイベントをクリックするとインスペクターに呼び出すメソッドが表示されるのでそこからメソッドをしていします。

ただし、このコンボボックスにはコンポーネントの全てのメソッドが一気に表示されるため、実装状況次第でてとんでもない量のメソッドが表示されます。

大量のメソッドのスクロールで選択が難しい場合は、代わりに Project にあるクリップのアセットファイルをを選択し、先ほどのアニメーションクリップのイベントをクリックするとインスペクターに以下のように表示されます。

この Funtion の項目にメソッド名を入力すれば先ほどのコンボボックスからメソッドを指定したのと同じような指定ができます。

スクリプトにコールバックを記述する

この設定したコールバックですが実際は「SimpleAnimation が設定されているゲームオブジェクトの中で指定した名前のメソッドが呼ばれる」動作になります。

以下のようにコールバックを記述してアニメーションを実行するとコールバックが呼び出されると思います。コードにはIL2CPPしたときにメソッドが削除されないように(何でもよいので)属性を付与しています。イベントの Function には OnAnimationCompleted を設定しています。

using UnityEngine;
using Takap.Utility;
using Sirenix.OdinInspector;

public class Sample : MonoBehaviour
{
    SimpleAnimation sanim;

    private void Awake() => this.SetComponent(ref this.sanim);

    // デバッグ用の実行(アセットのOdinでボタンを表示)
    [Button]
    public void PlayAnimation()
    {
        this.sanim.Stop();
        this.sanim.Play("Sample");
    }

    // アニメーションが終了したときに呼ばれるメソッド
    [CallFromAnimationClip]
    public void OnAnimationCompleted() => Debug.Log("アニメーションが終了しました。");
}

実行してみる

実行すると以下のようにイベントが呼び出されて、コンソールにログが出ているのが確認できます。

使用するときの注意事項

この方法は AnimationClip の Unity 標準機能(いつからこの設定が可能なのか把握していませんが)で終了を監視する実装をしないで済むので割と便利です。ただ「呼び出すメソッドの名前は動的に変更できない」ので少し注意が必要です。

複数の AnimationClip で同じ名前を指定した場合、問答無用で同じメソッドが呼び出され変更ができません。また同じ名前の別のメソッドがあるとそれが呼び出されることもあるのでコールバックに指定するメソッド名はゲームオブジェクト内でユニークになるように調整してください。

また不用意にスクリプト側のメソッド名を変更するとコールバックが呼び出されなくなる(ここら辺は SerializeField や UnityEvent と同じですが)なのでスクリプトの扱いは注意しましょう。

またイベントは今回は終了時にひとつだけ設定しましたが、複数設定することができるため任意のタイミングで任意のメソッドをいくつでも呼び出せます。AddEventボタンを押せばハンドラをいくつでも追加できます。開始、中間、終了でメソッドを呼び出したりできるので終了を監視するよりも柔軟なメソッド呼び出しができます。

以上、AnimationClip の Event を利用するでした。