【UniRx】Update()をObservableに変換する方法

  • 27
    いいね
  • 0
    コメント

UniRxについての記事のまとめはこちら


UniRxを使用するとUpdate()をObservableに変換して使う場合が多々あります。
今回はそのUpdateをObservableに変換する方法を紹介したいと思います。

注意

本投稿よりもこちらの記事のほうがより詳細に書いてありますので、こちらを御覧ください。
UniRx入門 その4 -Updateをストリームに変換する方法とメリット-

以下古い説明

Update → Observableに変換する

UpdateをObservableに変換する方法は2015/04/10の時点で3種類あります。

  • ObservableMonoBehaviour & UpdateAsObservable
  • ObservableUpdateTrigger & UpdateAsObservable
  • Observable.EveryUpdate

それぞれ微妙に違うので注意が必要です。

ObservableMonoBehaviour & UpdateAsObservable

【注意】UniRx 4.8以降、ObservableMonoBehaviourは非推奨となりました

ObservableMonoBehaviourとUpdateAsObservableの使用例
public class UniRxSample : ObservableMonoBehaviour
{
    public override void Start()
    {
        base.Start();

        UpdateAsObservable()
            .Subscribe(_ => Debug.Log("Update!"));
    }

    public override void Update()
    {
        //Updateをoverrideするときはbase.Update()の呼び出しを忘れない
        base.Update();   
    }
}

特徴

  • ObservableMonoBehaviourはMonoBehaviourの派生クラスで、継承して使う必要がある
  • UpdateAsObservable()でUpdateのタイミングが通知されるようになる
  • Componentが破棄されると勝手にDisposeされる
  • ストリームはIObservable<Unit>
  • ObservableMonoBehaviourにはUpdate以外の通知も用意されているので便利と言えば便利
  • Script Execution Order から他のスクリプトとの実行順序の細かい指定ができる

説明
UpdateAsObservableは内部的にはSubjectを持っており、Update()時にOnNextを叩いているだけのシンプルな仕組みになっています。(該当箇所)
そのため、UpdateをOverrideする際はbase.Update()の呼び出しをちゃんと追加してあげないとUpdateAsObservable()は動作しないので注意が必要です。

またObservableMonoBehaviourはいろいろイベントトリガが用意されておりこれを継承すれば万能ではあります。ですがObservableMonoBehaviourの継承ができない場面や意図的に継承したくない場合には使用できません。

【追記】

作者の@neueccさん曰く非推奨であり、UniRx 4.8以降でサポートされなくなりました。
代わりに後述のObservableUpdateTriggerを使いましょう。

ObservableUpdateTrigger

ObservableUpdateTrigger&UpdateAsObservableの使用例
using UniRx;
using UniRx.Triggers;
using UnityEngine;

public class UniRxSample : MonoBehaviour
{
    private void Start()
    {
        this.UpdateAsObservable()
            .Subscribe(_ => Debug.Log("Update!"));
    }
}

特徴

  • ObservableUpdateTriggerはUniRx.Triggers名前空間に定義されている
  • UniRx.TriggersをUsingに加えておけばUpdateAsObservable()を直接呼び出すことができる
  • 実体はObservableUpdateTriggerにある
  • 呼び出し時に裏で自動的にAddComponentされる(実際使うときはTriggerの存在は気にしなくて良い)
  • ObservableMonoBehaviourと内部的な仕組みは同じ

ObservableUpdateTriggerはイベントトリガごとに分割したものの1つです。
ObservableMonoBehaviourは継承が必要でしたが、こちらはただUsingを追加するだけなので使い勝手は高いです。

Observable.EveryUpdate

Observable.EveryUpdateの使用例
Observable
    .EveryUpdate()
    .Subscribe(x => Debug.Log(x));

特徴

  • staticメソッドとして定義されているのでMonoBehaviour以外の場所で使用できる
  • ストリームにはSubscribeしてからのフレーム数が流れてくる
  • SubscribeのDisposeは手動で行う必要がある(またはAddToを使ってGameObjectに紐付ける必要がある)

説明
Observable.EveryUpdateはstaticメソッドと定義されているため、MonoBehaviour以外の場所から呼び出して使うことができます。内部的にはMainThreadDispatcherのコルーチンの実行タイミングが通知されます。
注意点として、SubscribeのIDisposableを正しく管理する必要があり使用の際には注意が必要です(AddTo等を忘れずに付けておく必要がある)。

まとめ

  • 手っ取り早く使うならObservableMonoBehaviourを継承する ObservableMonoBehaviourは非推奨になりました
  • UniRx.TriggersをUsingに追加してUpdateAsObservable()を直接呼び出すのが最も簡単で使いやすい
  • Observable.EveryUpdateは使う場面がそんなにない