UnityのAnimationControllerの簡易的な解説

## 概要
備忘録を兼ねてUnityの **AnimationController** の使い方を書こうと思いました。
また、VRChatのAvatars 3.0を理解する上でも、AnimationControllerの設定は必要です。
**この記事がわかりにくい場合、参考リンクの動画を見たほうがわかりやすいと思います。**

## Unityにおけるアニメーション制作の概要
そもそも、Unityではアニメーション制作に使える機能として、下記の機能が用意されてます。

- C#でプログラミングして、直接Transformの値を制御してアニメーションさせる。
- アニメーションの内容を記録する機能を持った**AnimationClip**を再生する。
 - **AnimationClip**をAnimationコンポーネントで呼び出す **(旧式の機能)**
 - **AnimationClip**をAnimationControllerで呼び出す **(現在使われてる機能)**
- TimeLine機能を使う→主に映像制作で使われる機能

この記事で扱うのは **AnimationClip** と **AnimationController** のみです。
関係性としては **AnimationController** に再生したい **AnimationClip** を割り当てて **AnimationController** から **AnimationClip** を再生します。
なので、Animation内容であるAnimationClipを作成し、そのClipを呼び出すAnimationControllerの２つの作成と編集が必要になります。（C#のプログラムで動かす場合は、プログラムも必要）
![img.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149449/3ec5dce8-2881-f3b5-e480-e3fb1bb94d5c.png)
**余談**
AnimationControllerみたいに状態の遷移を管理する機能をもったものを一般的に「ステートマシン(状態遷移図)」といったりします。
ステートマシンっていうと堅苦しいですが、**自動販売機の仲間**とも言えます。
旧式のUnityのAnimationコンポーネントはプログラムから**AnimationClipを直接**呼び出してました。つまり、**AnimationControllerのような振る舞いをするものを自分でプログラムして作成する必要があった**わけです。

## AnimationClipの作成

![img.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149449/fa37ee78-c78d-dee6-643a-1760dce62071.png)

- AnimationClipを作成したいGameObjectをHierarchy上で選択する。
- その状態で メニューバーの[Window] > [Animation] > [Animation] を選択する。

![img.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149449/0225003e-c138-e686-7f64-0d0f1218352b.png)

- Animationのタブが開かれるので [Create] を押して、AnimationClipの名前を付けて保存する。
- Animationタブで編集が可能になるので、AnimationClipを編集する。

![img.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149449/ad4efd51-4e8f-7b43-802b-e1ea9d890cfe.png)

- 編集可能な状態

### 注意点

![img.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149449/3602321c-293e-2398-018a-4994bd96b8b2.jpeg)

- AnimationClipを作成した後に、AnimationさせるGameObjectの名前を変えると動かなくなる。(AnimationClipは名前で紐付けてる)
- AnimationClipを作成した後に、オブジェクトの階層構造を変えると動かなくなる。(AnimationClip作成時の階層構造を崩しちゃいけない)

## AnimationClipの編集

![img.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149449/0014b8ff-a904-61b1-3057-4c6f9847dcab.png)

- **編集したいAnimationClipに紐付けられれいるGameObjectをHierarchy上で選択する**
- Hierarchy上で対応したObjectを選択しないとAnimationタブが選択可能な状態にならない
- AnimationClipを新規作成する場合はAnimationタブのCreateNewClipから行う
- 編集するAnimationClipの変更は左上のドロップダウンを展開する

### キーの追加(Animation内容の作成)

[【Lecture:20 Unity】Unityでアニメーション！作って再生してみよう！【Beginner】](https://youtu.be/ozv0NvZsfQo?t=278)
上記の動画の4:38～がわかりやすいです。(リンクは4:38から再生されます）

## AnimationControllerを開いて編集する

![img.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149449/9e80fddd-3312-c17a-df4f-35643092b1ae.png)
AnimationControllerはAnimationClipを作成した時に、同時に作成されています。
Projectタブのどこにあるのか分からない場合…[AnimationClipを作成したゲームオブジェクトをクリック] > Hierarchyを確認してAnimatorコンポーネントのControllerをダブルクリック > Projectタブ内にあるAnimationControllerがハイライトされる。
Projectタブ内のAnimationControllerをダブルクリックすると、Animatorタブが開いて、AnimationControllerの編集が可能になります。

![img.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149449/8fb77bc6-2b3f-948c-9dc8-ca30694b46b8.png)

- 上記のような画面が出てくればOK

## AnimationControllerのステートとパラメータを設定する

![img.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149449/fa3eece2-a0ea-1d4b-b6f4-bc02cfa3aad8.png)
AnimationControllerを制御するにあたって、**パラメータの設定** と **ステートの設定** を行う必要があります。
**パラメータ**とは、ステートの条件に使用する変数です。
**ステート**とは、AnimationClipを呼び出す順番や呼び出す条件を決めたもの。
関係性としては、Motionの変数が1になった場合…Motionが1の時に遷移するステートが呼び出され、割り当てられたAnimationClipが再生される という関係です。

**余談**
VRChatのAvatars 3.0ではユーザーが自由に作成したAnimationControllerを動かすようにするための仕組みが提供されています。
なので、AnimationControllerの仕組みを理解した上で、Avatars 3.0に必要な設定を行う必要があります。
![img.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149449/e1daad7d-8198-480a-770e-38eaebc9b952.png)
**パラメータの作成**
[Animator]タブを開く > [Parameters]のボタンを押す > [＋]のボタンを押す > float,Int,Bool,Trigger から種類を選ぶ > Newのパラメータが作成される。

**AnimationClipをControllerに追加する**
ProjectタブからAnimationClipをAnimatotタブにドラッグ＆ドロップすると、AnimationControllerにClipが追加できる。

**追加できるパラメータの種類について**
float… 小数点。走る速度が変化するとモーションもだんだん変化してゆくみたいな時に使うイメージ。
int…整数。固定のモーションに切り替えるみたいな時に使うイメージ。
bool…0か1の値。武器を持ってない場合はモーションを変化させないみたいな条件に使うイメージ。
Trigger…スクリプトで有効にした後、AnimationController側で無効にしてくれる。プログラムからは呼び出すだけでいいようにしたい時に使うイメージ。

**ステートの作成**
![img.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149449/55971fc0-52df-136c-7a1d-9fe2a0e3bf2d.png)
ステートを作成したいクリップを選択した状態で右クリック > ［Make Transition］を押す > ステート先のAnimationClipを選択する。
その後、Inspectorからステートの条件設定を行う。

**ステートの条件設定**
![img.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149449/59e4953d-a4da-7c82-d075-116f5c8afe4e.png)

**ステート設定の簡易まとめ**

| AnimationControllerのオプション | 意味 |
|:-----------|:------------|
| Has Exit Time | 有効の場合、前のClipの再生が終わったら自動で再生され Exit Time の条件を満たすと終了。　無効の場合、Conditionsの条件を使って再生開始 |
| Exit Time | Has Exit Time が有効の場合、**Clipを何％再生したら終了するのか**決める 0.75の場合は75%までClipが再生されるとそのステートが終了する。 |
| Fixed Duration | 有効の場合、遷移時間は秒単位になる。 |
| Transition Duration | ステートが変化するのに要する時間 1秒なら1秒かけて遷移元と遷移先のモーションが合成されて変化する |
| Transition Offset | 遷移先のAnimationClipを再生する位置 0.5の場合、遷移先のAnimationを50％時点から再生する |

リファレンス：[アニメーション遷移 unity DOCUMENTATION](https://docs.unity3d.com/ja/2019.4/Manual/class-Transition.html)

**ステートの設定例**
任意のモーションに任意のタイミングで変化させたいような場合はだいたい以下の用になります
1.HasExitTimeのチェックを外す（conditionsが設定できるようになる）
2.conditionsの[＋]ボタンを押して項目を追加、ステートの条件にしたいパラメータを選ぶ
3.パラメータに対応した条件設定ができるので条件を設定する

| パラメータ | Conditionで使える条件 |
|:-----------|:------------|
| Float | Greater(以上) Less(以下) |
| int | Greater(以上) Less(以下) Equals(等しい) Not Equals(等しくない) |
| Bool | true と false |
| Trigger | なし |

**設定例**
![img.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149449/5b1debb5-cbf6-caca-b8d0-c1c792678041.png)
上記の場合、Motionというintのパラメータが 1 になった時に再生される というステートになります。

## 【余談】C#からAnimationControllerを制御するサンプルプログラム

```c#:CubeAnimation.cs
using UnityEngine;

public class CubeAnimation : MonoBehaviour
{
    //操作したいAnimationControllerを持ったGameObjectを割り当てる
    public Animator _animator;
    void Update()
    {
        // Int
        // 押したナンバーキーに対応したポーズを呼び出すイメージ
        if(Input.GetKeyDown(KeyCode.Alpha0))
        {
            _animator.SetInteger("Motion", 0);
        }
        if(Input.GetKeyDown(KeyCode.Alpha1))
        {
            _animator.SetInteger("Motion", 1);
        }       

        // float
        // speed に対応したモーションに変化させるイメージ
        float speed = 0.5f; // プレイヤーの移動スピード
        _animator.SetFloat("Float", speed);

        // Bool
        if(Input.GetKeyDown(KeyCode.B))
        {
            _animator.SetBool("Bool", true);
        } 

        // Trigger
        if(Input.GetKeyDown(KeyCode.T))
        {
            _animator.SetTrigger("Trigger");
        }        
    }

}
```

Animatorにパラメータを制御する関数が入ってるので、それを使います。
リファレンス：[Animator unity DOCUMENTATION](https://docs.unity3d.com/ja/current/ScriptReference/Animator.html)

## まとめ

他にもAnimationClipでは[アニメーションカーブ](https://docs.unity3d.com/ja/2018.4/Manual/animeditor-AnimationCurves.html)が設定できたり、[レイヤー機能](https://docs.unity3d.com/ja/2019.4/Manual/AnimationLayers.html)とか、Controllerのステートとかも色々設定がありますが、おおまかに要点をおさえました。
詳細については参考リンクなども確認してみてください。

## 参考リンク

- [【Lecture:20 Unity】Unityでアニメーション！作って再生してみよう！【Beginner】](https://youtu.be/ozv0NvZsfQo)
- [【Lecture:22 Unity】「Animator」を使いこなそう！～設定の詳細と基本的なスクリプト編～【Medium】](https://youtu.be/SGO9MMFHI54)
- [Unity Learn アニメーターコントローラー](https://learn.unity.com/tutorial/animator-controllers-2019-3) Unity公式のチュートリアル
- [アニメーションシステム概要 unity DOCUMENTATION](https://docs.unity3d.com/ja/2018.4/Manual/AnimationOverview.html)
- [Animator スクリプトリファレンス](https://docs.unity3d.com/ja/current/ScriptReference/Animator.html)