【Unity】AnimatorのステートにアタッチできるStateBehaviourの紹介

# はじめに
この記事は[Hamster Output Advent Calendar 2024](https://qiita.com/advent-calendar/2024/game_hamster)の21日目の記事です！

今回はStateBehaviourの紹介をしたいと思います。

# 実はAnimatorのステートにはスクリプトをアタッチすることができる

といっても、MonoBehaviourをアタッチできるという訳ではないですが...
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/0c90b1e1-746c-62da-c6d8-521d1afbdfbf.png)

代わりに、StateBehaviourを継承したスクリプトをアタッチすることができます。手動で作ると少し面倒なので、Animatorのステートを選択した後に、インスペクタからスクリプトを作るのが楽です。

AddBehaviour → New Script
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/91ae5ad2-7a35-80d3-2b4c-8b48c6d9e003.png)

作成されるとスクリプトがアタッチされます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/cdafd7a2-7b62-5206-24d5-cbf50bb810f7.png)


そして作られたソースコードはこちら。ほとんどコメントアウトされてます。下にメソッドの内容をまとめています。
```C#
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class IdleState : 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)
    //{
    //    
    //}

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

    // OnStateIK is called right after Animator.OnAnimatorIK()
    //override public void OnStateIK(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
    //{
    //    // Implement code that sets up animation IK (inverse kinematics)
    //}
}
```

それぞれのメソッドの内容は以下の通りです。

| メソッド名 | 内容 |
|-----------|-----------|
| OnStateEnter   | Stateの開始時に一度だけ呼ばれる |
| OnStateUpdate | State中に毎フレーム呼ばれる(UnityのUpdate) |
| OnStateExit | ステートが終了した時に呼ばれる|
| OnStateMove | RootMotionに関する処理を実行する場所 |
| OnStateIK | IKに関する処理を実行する場所 |

MoveとIKに関しては使ったことが無かったので、今回初めて内容を知りました💦

そして、IdleStateの中身をこのように変更しました。
```C#
using UnityEngine;

public class IdleState : StateMachineBehaviour
{
    override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
    {
        Debug.Log("Enter Idle State");
    }

    override public void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            animator.CrossFadeInFixedTime("Walk", 0.3f);
        }
    }

    override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
    {
        Debug.Log("Exit Idle State");
    }
}

```

そして実行するとしっかりとStartのログが出ています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/de24e4e9-8fdd-deed-dacc-e7e2ca657a67.png)

そして、スペースキーを押すと、Animationが遷移してExitのログが出てることが分かります。このようにステート内で処理を実行してAnimationの変更など様々なことができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/235d788c-3ff4-2ae3-2954-9ecdcc4cbda3.png)

# いつも何気に使っているAnimatorは実はStateMachineだった

設計とかを考えるようになって初めてステートマシンについて勉強をしましたが、実は身近に使っていたAnimator自体がステートマシンだったんですよね...

公式リファレンスにも書いてあります。

https://docs.unity3d.com/ja/2019.4/Manual/AnimationStateMachines.html

# ステートマシンを触りたいなという人におすすめしたい
AnimatorはGUIベースのステートマシンなので視覚的に見やすいところから使いやすいです。まだ、ステートマシン使ったことが無いけど興味がある...という人や、ステートマシン勉強したいなという人はぜひ触って見てください。

ただ、遷移条件をGUIで沢山作ると滅茶苦茶になるのでAnimationCrossFadeを使ったり、Exit用のステートを作ってStartStateに戻す処理を作ると見やすくなると思います。