【Unity】Animation Eventを活用する例

#目標
「Animation Event」機能を使うことで、Animationが再生されるたびにAnimation Eventの関数が自動的に呼び出されます。

本例では、「Animation Event」機能を利用し、Playerが手を振り始めた（つまり、「player_wave」というanimationの再生が始まった）時、自動的に「Hello」という文字が表示され、振り終わったら（つまり、「player_wave」の再生が終わった）自動的に「Bye」が表示されます。
![test.gif](https://qiita-image-store.s3.amazonaws.com/0/305759/99465119-195e-c3ef-9e5f-0976326c7459.gif)
#実現方法
###①PlayerのAnimationを作成します。
とりあえずUnity Asset Storeの無料「[Character Pack](https://assetstore.unity.com/packages/3d/characters/humanoids/character-pack-free-sample-79870)」を利用します。今度はBlenderで自分で作ってみたいと思います。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/305759/1cb10bfc-b754-7b9a-192a-657ee1cccdef.png)
この「Character Pack」の中でたくさんのAnimationがあるけど、この例で使うのは、「player_idle」と「player_wave」だけです。
###②Animationたちを繋げるAnimatorControllerを作成します。
「Animation」「Animator Controller」の詳細についてまだ詳しくない方はまずこちらへ :point_right: [Unity Manual](https://docs.unity3d.com/ja/current/Manual/AnimationOverview.html)

AnimatorControllerの名前は「PlayerAnimation」にします。
この例と関わるのは、「idle->wave->idle」です。
また、パラメータ「idle」と「wave」を作っておきます。「(wave==true) && (idle==false)」の時にAnimationが「idle」から「wave」に切り替えられます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/305759/dbe3f4e8-d075-aab3-abac-4e4ea36dfddd.png)
###③「②」のAnimatorController「PlayerAnimation.controller」をgameobject「player」にアタッチします。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/305759/4926fe1c-c260-75b5-3b38-ab7762567120.png)
###④AnimatorControllerを呼び出すコードPlayerController.csを作成します。
「PlayerController.cs」をgameobject「player」にアタッチします。
このコードは、ゲームが始まる時にAnimation「player_wave」を再生します。結果的には、ゲームが始まったらplayerが手を振ります。

```c#:PlayerController.cs
using UnityEngine;
using UnityEngine.UI;

public class PlayerController : MonoBehaviour
{
    private Animator m_animator;

    private void Start()
    {
        m_animator = GetComponent<Animator>();
        runAnimation("wave");
    }

    private void runAnimation(string animationName)
    {
        foreach (AnimatorControllerParameter param in m_animator.parameters)
        {
            m_animator.SetBool(param.name, false);
        }

        m_animator.SetBool(animationName, true);
    }
}
```
###⑤新規Textして、Sceneの適当の場所に放置します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/305759/6080172c-68db-7d25-8744-25db702c06af.png)
###⑥Animation「player_wave」にEventを追加します。
場所はAnimationの「Inspector->Animation->Events」です。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/305759/e9b6a92a-32f2-6e38-b225-c13ef5995fe3.png)
0.00sの位置（player手を振り始めようとする時）に「AddEvent」ボタンを押してEventを追加します。
関数名は「handleAnimationEvent」にします。
引数はStringの「waveBegin」にします。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/305759/202ec237-f539-977f-4d28-efc2619c7470.png)
同じように、「wave」が終わりそうとする時にもう一つのEventを追加します。
関数名は同じ「handleAnimationEvent」にします。
引数は「waveFinish」にします。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/305759/c5a75e26-a2ec-541e-6563-23fb8de1f067.png)
###⑦関数「handleAnimationEvent」を「PlayerController.cs」に追加します。
関数「handleAnimationEvent」はAnimation「player_wave」が再生される時に自動的に呼び出されます。
また、引数値が「waveBegin」だと、Textが「Hello」になり、引数値が「waveFinish」だと、Textが「Bye」になります。ここのTextは⑤で作ったTextです。

```c#:PlayerController.cs
using UnityEngine;
using UnityEngine.UI;

public class PlayerController : MonoBehaviour
{
    private Animator m_animator;
    private Text m_text;

    private void Start()
    {
        m_animator = GetComponent<Animator>();
        m_text = GameObject.FindGameObjectWithTag("Text").GetComponent<Text>();

        runAnimation("wave");
    }

    private void runAnimation(string animationName)
    {
        foreach (AnimatorControllerParameter param in m_animator.parameters)
        {
            m_animator.SetBool(param.name, false);
        }

        m_animator.SetBool(animationName, true);
    }

    // This function is called by the animation, always remember to maintain the animation
    private void handleAnimationEvent(string str)
    {
        switch (str)
        {
            case "waveBegin":
                m_text.text = "Hello";
                break;

            case "waveFinish":
                m_text.text = "Bye";
                break;

            default:
                break;
        }
    }
}
```
いかがでしょうか？
以上です。
:clap: