Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
9
Help us understand the problem. What is going on with this article?
@Nitudon

UnityのAnimatorで、StateMachineBehaviourを分離せずに制御してみる

More than 3 years have passed since last update.

あんまり調べても出てこなかったのでメモがてらに投稿しました
Animator周りの参考に少しでもなれば幸いです

StateMachineBehaviour

UnityにおけるAnimatorのステートのイベントを管理するコンポーネントです
主にAnimatorのステートにアタッチして使ったりします
OnStateEnter、OnStateExitといったステート周りのタイミングを管理しており、コールバックで各イベント時の処理を行うことができます
このサイトがわかりやすいので読んでみるといいと思います

Unity5 MecanimのStateMachineBehaviourと戯れる
テラシュールブログ
http://tsubakit1.hateblo.jp/entry/2015/05/01/032208

Animatorのステートにアタッチするので個人的に処理が分散しがちかなーと
今回はこの問題を解決するために少しだけ工夫してみました

StateMachineBehaviourを制御する

ここからが本題なんですが、 実はStateMachineBehaviourってリファレンスで普通に取得できます
それがGetBehaviour、使い方はGetComponentと一緒です
例えばTというStateMachineBehaviourを継承したものを用意した場合は
T hoge =Animator.GetBehaviour<T>();
T[] hoges = Animator.GetBehaviours<T>();

みたいな感じで
GetBehaviourはアニメーター全体からBehaviourを取得するため、任意のBehaviourで都合よく取得したい場合などで難しい場合があります、その辺は注意です

なんで下みたいな感じでステートにはアタッチするけど、処理自体はMonoBehaviourで管理するみたいなこともできます!
まずはMonoBehaviourにアタッチするスクリプトです

TestModel.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TestModel : MonoBehaviour {

    [SerializeField]
    private Animator _animator;

    private TestBehaviour[] _behaviour;

    private void Start()
    {
        _behaviour = _animator.GetBehaviours<TestBehaviour>();

        for (int i = 0; i < _behaviour.Length; ++i)
        {
            _behaviour[i].SetStateEnterEvent(Test);
            _behaviour[i].SetStateEnterEventWithState(InfoTest);
        }
    }

    private void Test()
    {
        Debug.Log(_animator.GetCurrentAnimatorClipInfo(0)[0].clip.name);
    }

    private void InfoTest(AnimatorStateInfo info)
    {
        Debug.Log(info.length);
    }
}

今回はBehaviourを全部取得してすべてのイベントを共通で登録しました
もちろん単体で取得しても、別々のBehaviourを設定してイベントを登録しても大丈夫です

続いては肝心のStateMachineBehaviour側です

TestBehaviour.cs
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TestBehaviour : StateMachineBehaviour {

    // ステートに入ったときのイベントリスナー
    private Action OnStateEnterListener;

    // ステートに入ったときのイベントリスナー
    private Action<AnimatorStateInfo> OnStateEnterWithStateListener;

    // イベント設定
    public void SetStateEnterEvent(Action action)
    {
        OnStateEnterListener += action;
    }

    // イベント設定
    public void SetStateEnterEventWithState(Action<AnimatorStateInfo> action)
    {
        OnStateEnterWithStateListener += action;
    }

    //StateMachineBehaviourのステート遷移時のコールバック
    public override void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
    {
        if (OnStateEnterListener != null)
        {
            OnStateEnterListener();
        }

        if (OnStateEnterWithStateListener != null)
        {
            OnStateEnterWithStateListener(stateInfo);
        }

        base.OnStateEnter(animator, stateInfo, layerIndex);
    }
}

見ての通り、リスナーを用意し、外部からの登録を可能にしています
これを呼んであげればいいだけです

今回はTestModelをUnityちゃんにアタッチして、TestBehaviourを各ステートにアタッチします

実行して適当にアニメーション再生してみた結果がこんな感じ
ちょっとこれだけだと本当にできてるか伝わりませんが、アニメーションが遷移するたびにそのアニメーションクリップ名とモーションの時間をログにはいています
キャプチャ.PNG

面倒なパターンもあるので一概にマストとは言えませんが状況に応じては設計がすっきりするかな?とも思います

間違っている点や質問などあればお願いします!

9
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Nitudon
Unityでゲーム作ってます ブログで技術記事書いてるので良ければ覗いてみてください
qualiarts-inc
QualiArtsは皆様に長く愛されるエンターテイメントを提供するため、スマートフォンゲームの企画、開発、運営を行っております。

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
9
Help us understand the problem. What is going on with this article?