[Unity] Animator Controllerでできることメモ(非エンジニア)

Unityバージョン:2019.4.25f1
ここではStateとTransitionの説明は省いています
StateとTransitionの説明については以下を参考にしてみてください

Animator Controllerとは

アニメーションの遷移を管理するためのファイル
Scriptで遷移をすることも可能ですがAnimator Controllerを使うことで視覚的に遷移の管理が可能になる
デメリットはStateの数が増えるとごちゃごちゃする

Parameter

Stateの遷移やBlendTreeに使用する値
Transitionに使用したいParameterを指定して遷移の条件に使う
Transitionの遷移条件に複数のParameterを設定することもできる

Trigger trueを使用するとfalseにリセットされるParameter
Bool      trueとfalseの値を持てるParameter
Int         整数の値を持てるParameter
Float     浮動小数(0.1とか)の値を持てるParameter ※Scriptで変数に値を代入するときは数字の後にfをつける

int, floatのTransitionの条件指定について
Greater
    指定した値より大きい   Parameterの値 > 指定した値
Less         指定した値より小さい   Parameterの値 < 指定した値
Equals     指定した値と同じ     Parameterの値 == 指定した値
NotEqual 指定した値と同じではない Parameterの値 != 指定した値
※EqualsとNotEqualはintのみ設定できる

参考元
Unity Animator 設定等について
http://otaty.blog.fc2.com/blog-entry-23.html

SET:値を入力する
アニメーションの遷移を行うときに値を変更する

using System;
using System.Collections;
using UnityEngine;

public class SampleScript1 : MonoBehaviour //class名はファイル名と同じにする
{
    private Animator animator;//変数の宣言
    void Start()
    {
        //オブジェクトにアタッチされているAnimatorを変数へ代入
        animator = GetComponent<Animator>();
        
        //値を入力
        animator.SetTrigger("ParameterA");     //Triggerをtrueにする
        animator.SetBool("ParameterA", true);  //Triggerはbool型なのでこれでも同じ
        animator.ResetTrigger("ParameterA");   //Triggerをfalseにする
        animator.SetBool("ParameterB", true);  //bool変数をtrueにする
        animator.SetBool("ParameterB", false); //bool変数をfalseにする
        animator.SetInteger("ParameterC", 1);  //int変数に1を代入する
        animator.SetFloat("ParameterD", 1.0f); //float変数に1.0fを代入する
    }
}

↓SetFloatだけもう少し細かく値が設定できるようだ
Unityスクリプトリファレンス SetFloat
https://docs.unity3d.com/ja/current/ScriptReference/Animator.SetFloat.html

GET:値を取得する
If文やswitch文などで使う

using System;
using System.Collections;
using UnityEngine;

public class SampleScript2 : MonoBehaviour //class名はファイル名と同じにする
{
    private Animator animator;//変数の宣言
    void Start()
    {
        //オブジェクトにアタッチされているAnimatorを変数へ代入
        animator = GetComponent<Animator>();
        
        //Consoleウィンドウに出力 Consoleの場所:Window >> General >> Console
        Debug.Log(animator.GetBool("ParameterA"));    //Triggerの値を出力
        Debug.Log(animator.GetBool("ParameterB"));    //bool変数の値を出力
        Debug.Log(animator.GetInteger("ParameterC")); //int変数の値を出力
        Debug.Log(animator.GetFloat("ParameterD"));   //float変数の値を出力
        //if文
        if(animator.GetBool("ParameterB")){
            //処理 条件:true
        }
        else if(animator.GetBool("ParameterB") == false){
            //処理 条件:false
        }
        if(animator.GetInteger("ParameterC") < 0){
            //処理 条件:0未満
        }
        else if(animator.GetInteger("ParameterC") >= 0){
            //処理 条件:0以上
        }
        if(animator.GetFloat("ParameterD") < 0f){
            //処理 条件:0未満
        }
        else if(animator.GetFloat("ParameterD") >= 0f){
            //処理 条件:0以上
        }
    }
}

Unityマニュアル Animation Parameters
https://docs.unity3d.com/ja/2018.4/Manual/AnimationParameters.html

Stateの状態を取得

指定したStateが再生中かを取得できる
Transitionで遷移中かを取得できる

遷移中や特定のStateに遷移後などに処理を入れたい場合に組み合わせて使う

using System;
using System.Collections;
using UnityEngine;

public class SampleScript3 : MonoBehaviour //class名はファイル名と同じにする
{
    private Animator animator;//変数の宣言
    void Start()
    {
        //オブジェクトにアタッチされているAnimatorを変数へ代入
        animator = GetComponent<Animator>();
        
        //"StateA"が再生中か、再生中ならtrue 違うならfalseの値
        if(animator.GetCurrentAnimatorStateInfo(0).IsName("StateA")){
            //処理 条件:"StateA"が再生中
        }
        else if(!animator.GetCurrentAnimatorStateInfo(0).IsName("StateA")){
            //処理 条件:"StateA"が再生中ではない
        }
        else if(animator.GetCurrentAnimatorStateInfo(0).IsName("StateA") == false){
            //この記述でも上記と同じ意味 (条件:"StateA"が再生中ではない)
        }
        //Stateが遷移中かどうか、遷移中ならtrue 違うならfalseの値
        if(animator.IsInTransition(0)){
            //処理 条件:遷移中
        }
        else if(!animator.IsInTransition(0)){
            //処理 条件:遷移中ではない
        }
        else if(animator.IsInTransition(0) == false){
            //この記述でも上記と同じ意味 (条件:遷移中ではない)
        }
    }
}

(0)はレイヤー番号
AnimatorウィンドウのLayersタブのレイヤーが一番上から0,1,2...となる

遷移中にさらに遷移する

遷移中の挙動を管理する方法として
TransitionのInterruption Sourceで設定する方法がある
詳細は以下のサイトを参考にしてみてください

【Unity】Animator Controllerをマスターして自由で自然なモーション再生!複雑な各設定項目を全て解説
https://light11.hatenadiary.com/entry/2019/04/11/005147

Blend Tree

一つのState内に複数のアニメーションを設定して値の変化で切り替えることができる
例えば歩きと走りのアニメーションを設定してスピードの値の変化で歩きから走りへスムーズに切り替えることができる

Blend TreeのMotionをいじっているとアニメーションのBlend結果がバグる時がある その時はStateを削除して作り直すと良い

Blend Treeの作成
AnimatorウィンドウのStateの上で右クリックしてCreate new BlendTree in stateを選択するとInspectorウィンドウのMotionの項目がBlend Treeになる
StateをダブルクリックするとBlendTreeを設定できる

Blend Treeにアニメーションを追加
AnimatorウィンドウのStateをダブルクリック後にBlendTreeのノード(Blend Treeと書かれたグレーの四角いやつ)を選択しInspectorウィンドウでを押しAdd Motion Fieldを選択すると項目が追加されるのでMotionの項目でアニメーションを選択
1Dの場合はThresholdの項目で切り替わる目安の値をどのくらいにするか設定できる
Automate Thresholdsにチェックが入っていると自動で設定される
時計のようなマークの項目はアニメーションの再生スピード

Blend Type(ノードのInspectorウィンドウの項目)
参照する値が、1つなら1Dにする、2つなら2D~にする
2Dならダメージを受けた方向でアニメーションを変えるということもできる
アナログスティックの入力方向でアニメーションを切り替えるとかにも使えるようだ
(Typeの違いの詳細は以下のサイトを参考にしてみてください)

【Unity】Blend Treeをちゃんと理解してモーションブレンドを極める
https://light11.hatenadiary.com/entry/2019/04/18/224048

Parameter(ノードのInspectorウィンドウの項目)
参照する値を指定する(float型のみ)
デフォルトはAnimatorウィンドウのParameterタブの一番上にあるfloat型のParameterが設定されている
Parameterが存在しない場合はParameterが自動で生成され設定される

Unityマニュアル Blend Tree
https://docs.unity3d.com/ja/2018.4/Manual/class-BlendTree.html

Layer

AnimatorウィンドウのLayersタブでレイヤーを管理できる
翼の動きだけレイヤーを分けて管理したり、武器毎のアニメーションの切り替えをレイヤーで管理したりできる

  • 各レイヤーはウェイトの有無に関わらず全レイヤー動作しているっぽい
    なのであまりレイヤーは増やしたくない

  • レイヤーが分かれていれば同じState名を付けられる

  • ウェイトは0〜1で指定する 0で影響なしになる

  • 複数のレイヤーをウェイト1にするとLayersタブで一番下のレイヤーが優先される

  • レイヤーの設定はレイヤー名の右にある歯車をクリックすると行える

Maskは部分的に動きを変える場合に必要になる
Avatar Maskの作り方

  1. 3DモデルのInspectorウィンドウのRigのAvatarDefinitionからCreateFromThisModelを選択してskeletonを作成する

  2. Projectウィンドウから右クリック >> Create >> Avatar Mask で作成

  3. AvatarMaskのInspectorウィンドウのTransformで作成したskeletonを選んでImport skeletonを押す

  4. できたskeletonの項目から動かさないボーンのチェックを外す

Syncにチェックすると別のレイヤーのStateとTransitionを流用しアニメーションの差し替えができる

Blendingは他のレイヤーへの影響の仕方を指定する
override(動きを上書き)かadditive(動きを加算)か選べる
overrideにしてウェイトをScriptで0から1へ変更すればレイヤーを切り替えることができる
Scriptでウェイトの変更

using System;
using System.Collections;
using UnityEngine;

public class SampleScript4 : MonoBehaviour //class名はファイル名と同じにする
{
    private Animator animator;//変数の宣言
    void Start()
    {
        //オブジェクトにアタッチされているAnimatorを変数へ代入
        animator = GetComponent<Animator>();
        
        //"Second Layer"はウェイトを変えたいレイヤー名、数字でウェイトを指定0~1
        animator.SetLayerWeight (animator.GetLayerIndex("Second Layer"), 1);
        //SetをGetに書き換えればウェイト値の取得ができる
        Debug.Log(animator.GetLayerWeight (animator.GetLayerIndex("Second Layer")));
    }
}

Unityマニュアル Animation Layers
https://docs.unity3d.com/ja/2018.4/Manual/AnimationLayers.html

Sub-State

Sub-Stateの中にStateを格納できるのでStateを整理して見やすくできる

Sub-Stateの外にあるStateの名前とSub-Stateの中のStateの名前は同じにできるのでScriptでState名を条件にしている場合はこのことを考慮する
キャラの状態ごと(手に何かを持っているとか)にSub-Stateでまとめておいて 中のState名(待機、移動など)を同じにして管理することもできる

AnimatorControllerファイルを実行中に切り替える

AnimatorControllerを動的(ゲーム実行中の状況に応じて)にアタッチして切り替えることができる
レイヤーを増やしたくない場合はこちらを使う
StateとTransitionをそのまま流用したい場合はAnimator Override Controllerを作成すればアニメーションの変更だけで済む

using System;
using System.Collections;
using UnityEngine;

public class SampleScript5 : MonoBehaviour //class名はファイル名と同じにする
{
    private Animator animator;//変数の宣言
    void Start()
    {
        //オブジェクトにアタッチされているAnimatorを変数へ代入
        animator = GetComponent<Animator>();
        
        //Resourcesフォルダの"Animator/AnimatorA"のAnimatorControllerをアタッチする
        animator.runtimeAnimatorController = Resources.Load<RuntimeAnimatorController>("Animator/AnimatorA");
    }
}

Resources.Load
Resources.LoadでResourcesフォルダ内にあるファイルを呼び出すことができる ResourcesフォルダはAssetフォルダ内のどこにあっても良いがResourcesというフォルダ名は変えてはいけない

"Animator/AnimatorA"
"〇〇"でResourcesフォルダ内の場所とファイル名を指定している
上記はResourcesフォルダのAnimatorフォルダのAnimatorAというファイルを指定している

上記のScriptではvoid Start(開始時)でアタッチしているがvoid Update(毎フレーム処理)内のif文やKey入力処理に合わせて記述すれば動的にアタッチできる
※アタッチする時に遷移の状態は引き継がれないので注意

Transitionを使わないStateの遷移

Any Stateを使わずに強制的に遷移したいならこの方法がいいかもしれない

using System;
using System.Collections;
using UnityEngine;

public class SampleScript6 : MonoBehaviour //class名はファイル名と同じにする
{
    private Animator animator;//変数の宣言
    void Start()
    {
        //オブジェクトにアタッチされているAnimatorを変数へ代入
        animator = GetComponent<Animator>();
        
        //"AnimationA"を再生
        animator.Play("AnimationA");
        
        //現在のアニメーションから"AnimationB"へスムーズに移行
        animator.CrossFade("AnimationB",0.0f,0,0.0f);
    }
}

CrossFade
Transitionを使わずにScriptでStateの遷移を行なう際にアニメーションをスムーズに切り替えるための処理
数字は遷移時間(割合?), レイヤー番号, アニメーション開始位置0~1を指定している
遷移時間は遷移先のアニメーションの長さに依存するので1フレームしかないアニメーションに遷移する場合はフェードは起こらない

参考元
【UnityC#講座】ユニティちゃんでもっとAnimator Controllerを上手く使いたい
https://unity-shoshinsha.biz/archives/tag/animator-crossfade

Unityスクリプトリファレンス CrossFade
https://docs.unity3d.com/ja/current/ScriptReference/Animator.CrossFade.html

Stateの逆再生

StateのInspectorウィンドウのSpeedの項目の下のMultiplierにFloat型Parameterを設定できる
このParameterの値をー1にすると逆再生される
0なら停止、1なら順再生される
Scriptで変更する必要がなければSpeedの値を変更するだけで良い
梯子はしごの昇降アニメーションなどで利用できる

Stateを途中から再生

StateのInspectorウィンドウのMotion Timeの項目にFloat型Parameterを設定できる
このParameterの値が0.5ならアニメーションの真ん中から再生される
状況に応じて再生箇所を変えたい場合は利用できる

StateにTag付け

StateのInspectorウィンドウのTagに名前をつければ大まかなStateの分類が可能、Tag名の取得は以下のように記述する

// if文の条件などに使える
animator.GetCurrentAnimatorStateInfo(0).IsTag("TagName")

参考元
UnityのAnimatorの状態にタグを設定し条件を簡単にする
https://gametukurikata.com/animationanimator/animatorstatetag

Spineデータの再生

Spineデータの場合は以下のScriptファイルをStateのInspectorウィンドウのAdd Behaviourから追加してアニメーションを指定する必要がある

1、Create C#Scriptでファイル名はclass名(AnimationNameScript)と同じにして以下を記述する

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Spine;
using Spine.Unity;

public class AnimationNameScript : StateMachineBehaviour //class名はファイル名と同じにする
{
	public string animationName;
	override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) {
		SkeletonAnimation anim = animator.GetComponent<SkeletonAnimation>();
		anim.state.SetAnimation (0, animationName, true);
	}
}

2、追加したらAnimationNameの項目にそのStateで再生したいアニメーションの名前※を記述する
※Motionの項目で選択したアニメーションと同じ名前

↓詳しい手順は以下に記載しています

※勉強中ですので説明が間違っているかもしれません自分でも確認してみてください

この記事が気に入ったらサポートをしてみませんか?