本日は UniRx の小ネタ枠です。
ObservableStateMachineTriggerを使ってUniRxでAnimatorのコールバックを管理する手順を記事にします。
ObservableStateMachineTrigger
UniRx で提供される StateMachineBehavior のコールバックを Observable に変換する機能です。
StateMachineBehavior は Animator にアタッチすることで様々なコールバックを取得できます。
つまり、この機能を利用すると Animator のコールバックを UniRx で操作することができます。
UniRxのインポート手順
UniRxのインポート手順は以下の記事を参照ください。
bluebirdofoz.hatenablog.com
Animatorを持つモデルを作成する
ObservableStateMachineTrigger の動作を確認するため、Animator コンポーネントを持つゲームオブジェクトを作成します。
今回はホロモンモデルを利用しました。
Animator コンポーネントに設定する AnimatorController も作成します。
待機中のアクションと、物を探すアクションの2つのステートを遷移する AnimatorController を作成しました。
シーンに配置したホロモンモデルの Animator コンポーネントに、作成した AnimatorController を設定します。
StateMachineBehaviorの設定
StateMachineBehavior はデフォルトで設定されていないので、手動で追加する必要があります。
AnimatorController の画面を開き、[Add Behavior]から ObservableStateMachineTrigger を選択します。
これで AnimatorController に ObservableStateMachineTrigger が追加されました。
サンプルスクリプトの作成
動作確認用のサンプルスクリプトを作成します。
物を探すアクションのステートについて、State の開始をイベントトリガーとする OnStateEnterAsObservable() と、State の終了をイベントトリガーとする OnStateExitAsObservable() の動作を確認するサンプルスクリプトを作成しました。
・AnimationUniRxTest.cs
using System.Collections; using System.Collections.Generic; using System; using UnityEngine; using UniRx; using UniRx.Triggers; public class AnimationUniRxTest : MonoBehaviour { // Start is called before the first frame update void Start() { // Animatorコンポーネントの参照を取得 Animator animator = this.GetComponent<Animator>(); // AnimatorからObservableStateMachineTriggerの参照を取得 ObservableStateMachineTrigger trigger = animator.GetBehaviour<ObservableStateMachineTrigger>(); // Stateの開始イベント IDisposable enterState = trigger .OnStateEnterAsObservable() .Subscribe(onStateInfo => { AnimatorStateInfo info = onStateInfo.StateInfo; if(info.IsName("Base Layer.LoopAction")) { Debug.Log("Enter to LoopAction"); } }).AddTo(this); // Stateの終了イベント IDisposable exitState = trigger .OnStateExitAsObservable() .Subscribe(onStateInfo => { AnimatorStateInfo info = onStateInfo.StateInfo; if (info.IsName("Base Layer.LoopAction")) { Debug.Log("Exit from LoopAction"); } }).AddTo(this); } }
動作確認
シーンを再生して動作を確認します。
Parameter を変更して物を探すアクションのステートに遷移すると、物を探すステートの開始が検出されました。
再度、Parameter を変更して待機中のアクションのステートに戻ると、物を探すステートの終了が検出されました。
その他のトリガー
他にも以下のトリガーを設定できます。
・OnStateIKAsObservable()
・OnStateUpdateAsObservable()
・OnStateMachineEnterAsObservable()
・OnStateMachineExitAsObservable()
以下は OnStateUpdateAsObservable() を利用し、NormalizedTime の値をデバッグログに出力した例です。
// StateのUpdateイベント IDisposable updateState = trigger .OnStateUpdateAsObservable() .Subscribe(onStateInfo => { AnimatorStateInfo info = onStateInfo.StateInfo; if (info.IsName("Base Layer.LoopAction")) { Debug.Log("NormalizedTime : " + info.normalizedTime.ToString()); } }).AddTo(this);
以下の通り、物を探すステートにとどまり続ける限り、normalizedTime の値を取得し続けます。
アクションがループしているため、1 ループを 1.0 として normalizedTime は増加し続けているのが分かります。