UnityのAnimation・AnimatorControllerについて解説

この記事は [Unity Advent Calendar 2019](https://qiita.com/advent-calendar/2019/unity) 19日目の記事です。


#はじめに
アニメーションについて知っておくと良い機能を記事にしたいと思います。

#環境
Unity2019.2(Unity2017～Unity2019)

#UnityにおけるAnimation制御
* **AnimatorControlar**
* Timeline(Unity2017以降)
* PlaylableAPI(Unity2017以降)

今回はAnimatorControlarでの方法を解説
※Timelineについては未解説

AnimatorControlarは正直絶妙に使いにくいので
PlaylableAPIでフルコーティングできるならそれに越したことはないです。
初心者にはあまりオススメ出来ませんが.......

##AnimatiorControllerのダメなところ

あまりまとめて解説されている記事がない

Animatorの現在のステートを取得する方法が微妙なものしかなく
スクリプト内のステートと同期が大変
（そもそもAnyStateを用い現在ステートを取得しないようにするのがいいと思われる。）

#機能紹介
##Animation
###AnimationClip(.anim)
(エディタ上では容量がかなり大きいが、ビルド後かなり小さくなる)

* 手動で作成(スプライトアニメーション等)
例 http://tsubakit1.hateblo.jp/entry/2016/01/29/000017

* fbx等3Dのモーションデータ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308905/f2d30f46-d3b8-0078-2250-e19c7abaded6.png)
[Humanoid/Generic](#generichumanoid)を選択
自動的にKeyframeReductionが行われるため注意が必要
(精度がいいとは言えないので、違和感がある場合OFFにするほうが良い)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308905/1cdfab6b-d235-9763-ba89-3d87b44f5950.png)


* スクリプトで作成
 * [GameObjectRecorder](https://docs.unity3d.com/2019.2/Documentation/ScriptReference/Animations.GameObjectRecorder.html)(UnityのバージョンごとにAPIが違うので注意)
　　　　

 * [AnimationUtility](https://docs.unity3d.com/ja/2017.4/ScriptReference/AnimationUtility.html)(バインド名等取得が難しいのでGameObjectRecorderと併用したほうが良いと思われる。)

###Generic/Humanoid
* Humanoid
3Dの人型キャラクター及びそれに準ずるボーン構成がされているもののみ
各ボーンのTransformはAnimatorより取得可能([Animator.GetBoneTransform(HumanBodyBones humanBoneId)](https://docs.unity3d.com/ScriptReference/Animator.GetBoneTransform.html))
  * メリット
   Humanoid同士ならアニメーションのリターゲットが可能！
  * デメリット
    リターゲットになるためGenericよりは精度が悪くなってしまう

本気で使おうとするとモデル側の仕様がかなり厳しくほとんどのモデルは
厳密には対応していない場合が多い（ローカル回転軸の設定が少しがばがばなため）
そのためHumanoid設定されていてもHumanoidでリターゲット等きっちりリターゲットされて動く保証はない
アニメーションのリターゲットはDCCツールもしくはアセット（例UmotionPro等）上で行い
同じボーン構造にベイクしたモーションをHumanoid経由で用いるほうがよい

* Generic
HumanoidではHumanoidのボーンのみアニメーションを動かすことができるが
Genericではすべてのアニメーションを格納可能

  
###AnimationEvent
Animation中にUnityEvent(Publicな関数等)を呼び出せるもの
主にエフェクト生成、当たり判定などなど
アニメーション中のアクションのtriggerとして用いる
スクリプトで秒数等持つ必要が無くなり便利
※Animationをブレンドを行う場合、ブレンドされている部分が呼び出されにくくなくなるので注意

###AvatorMask
部分的にアニメーションの影響を切ることができる機能
[Humanoid/Generic](#generichumanoid)の両方に対応している
AnimatorControlarの[Layer](#layers)にてよく使われる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308905/2feccd24-e9d9-3033-ccb0-49a03990069f.png)



###RootMotion
fbx等のアニメーションデータにはその場を動いてアニメーションするものがある
例　[Miximo check In Place](https://www.mixamo.com/#/?page=1&query=walk) 
![ttt.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308905/3f36c7a0-f597-0e2d-d987-4df9bdb45a60.gif)
その移動量をそのままAnimatorのAnimatorのコンポーネントがついたTransformに適用するもの
スクリプト制御にすると細かい動きが難しいので、こちらを利用することで細かい動きまで再現可能
※rigidbodyを用いた場合、空中動作がおかしい感じになるため、RootMotionと非RootMotionの切り替えが必要となる

AnimatorコンポーネントのApplyRootMotionにチェックを入れることで利用可
また、アニメーションデータもRootMotionに対応しておかなければならない

##AnimatorControlar
###Parameters
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308905/a4d578ca-1b01-00ed-6d18-869eb7a3ae09.png)
Float,Int,Bool,Trigger型で設定可
このパラメータでステートマシンの状態を変化させる
※Trigger型は個人的には非推奨,一度ONになるとスクリプトから取り消せないため、
キャンセル等を行う場合危険となる、なのでBool型+[StateMachineBehaviour](#statemachinebehaviourcscript)を利用すべきである

###ステートマシーン
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308905/192a2af3-0f1d-0dbd-a8c9-ad33e83ca8ac.png)



* Entry  実行時最初にステートマシーンに入るもの
* AnyState  条件さえ満たせば現在のステートを上書きできるもの
* ExitState  ここを通過後Entryにもどる(主にAnyStateと一緒に利用)

* State
 * State(Empty) AnimationClipを一つのみ格納可能
 * BlendTree　AnimationClipを複数格納しParamatorsの値でブレンドを行う
 

 * SubStateMachine　(フォルダ管理,[スクリプトでのステート取得](http://fu-unity.hatenablog.com/entry/2015/06/13/235349)にも利用可)
* Transitions
Parametersを用いたステートマシン制御＆アニメーションのブレンド具合を調節する



###Layers
レイヤー機能
複数レイヤーを用いることでアニメーションの上書き/部分的制御/ブレンドを行うことができる
例　[AvatorMask](#avatormask)と一緒に用い下半身と上半身の動きを分割し武器によって上半身だけアニメーションを変更したり、
上書きでダメージ等モーションキャンセル系をはさんだりなど
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308905/f64bf773-dfc9-58b4-cc01-a5bfae7209b8.png)


###StateMachineBehaviour(C#Script)
[State](#ステートマシーン)にのみ割り当てが可能なC#スクリプト
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308905/8a0e220f-a19b-8d82-c3d4-040225fa3fc0.png)

※非MonoBehaviour
シングルトン化されているスクリプトへのアクセスは可
Animatorへのアクセスが可

下記関数以外は正直使うことはあまりない
//このスクリプトを割り当てしたステートが呼び出された、最初のUpdate()のタイミングで実行
**OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)**


例　キャンセル可能なTrigger(bool)型

```c#:ChangeAnimatorPrm.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ChangeAnimatorPrm : StateMachineBehaviour
{
    [SerializeField]
    private string prmName;
    [SerializeField]
    private bool value=false;
    
    //このスクリプトを割り当てたステートに入ったらboolをfalseにすることにより、Boolをキャンセル可能なTrigger型として使う
    override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
    {
        animator.SetBool(prmName, value);
    }
}

```



###IK(Humanoid時のみ)
これは[FinalIK](https://assetstore.unity.com/packages/tools/animation/final-ik-14290)の完全劣化であると思うため解説なし

#その他新機能
[AnimationRiging](https://docs.unity3d.com/Packages/com.unity.animation.rigging@0.2/manual/index.html)(Unity2019.1以上)
リギング作業をUnity上で行うことができる
以前までは標準機能ではConstraintのみしかなかったがこれにより
IKを細かく設定できる
アニメーションを作るまでは必要はないだろうがこれにより
補助ボーン系の制御＆FinalIKの一部代用はできるのではないだろうか

#まとめ
Unityのアニメーションには仕様がかなり多く
断片的に覚えているだけではかなり使いづらいものになっている
ベースとなる機能はUnity5以降あまり更新は入っていないためほとんどの記事は使えるのがまだ救いである