PG日誌

各記事はブラウザの横幅を1410px以上にすると2カラムの見出しが表示されます。なるべく横に広げてみてください。

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

あるアニメーションが終了したとき(=AnimationClipの終了時)にコールバックを受け取る方法の紹介です。

背景

少し前まで Unity が公開していた(今はアーカイブ化されて更新終了してる) SimpleAnimation を使っている時に、あるアニメーションの終了時にイベントを受け取る方法です。既存の記事では、normalizedTime が 1 になるのをUpdateで監視する方法がよく紹介されていますので、ここではそれとは違う実現方法を紹介したいと思います。本方法では Update メソッドに監視処理を実装しません。

注意:

今回の方法はアニメーターを使った場合どうなるか確認していません。

モバイル向け程度の軽い2Dゲームの場合、AnimationController は条件設定がやや面倒ですが DOTween だといちいち実行しないと動作確認ができない(&いちど作成した複雑なアニメーションの動作変更はそれなりに読解力が必要)なので SimpleAnimation + AnimationClip は Editor から動作を確認しながら編集は Unity 上での WYSIWYG 的な実装は割と現実的な解かと思います)

確認環境

Unity のバージョンは 2020.3 LTS を使用しています。

  • Unity 2020.3.2f1

また、本記事では特に関係ないですが実装環境は以下の通りです。

  • Windows10
  • VisualStudio2019

やりかた

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

SimpleAnimation と AnimationClip の準備

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

f:id:Takachan:20210413005646p:plain

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

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

f:id:Takachan:20210413010008p:plain

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

f:id:Takachan:20210413010347p:plain

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

f:id:Takachan:20210413010941g:plain

AnimationClip にイベントを追加する

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

f:id:Takachan:20210413011116p:plain

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

f:id:Takachan:20210413011400p:plain

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

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

f:id:Takachan:20210413011500p:plain

この 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("アニメーションが終了しました。");
}

実行してみる

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

f:id:Takachan:20210413013141g:plain

使用するときの注意事項

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

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

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

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

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