【Unity】【UniRx】独自のObservableを作る方法まとめ

この記事ではUniRxで、Observable.Timer()などのように元から用意されているファクトリメソッドを使わず、
自分自身で処理を定義してObservableを作る方法をまとめました。

Unity2019.2.6

最もちゃんとやるならIObservableを実装

独自のObservableを作るうえで最もちゃんと実装する方法はIObservableを実装する方法です。

using UniRx;
using System;

public class Example : IObservable<Unit>
{
    public IDisposable Subscribe(IObserver<Unit> observer)
    {
        // 色んな処理を書く

        return Disposable.Empty;
    }
}

ただこの方法は一々クラスを作らなければならないし、
なによりきちんとした設計でObservableを作るのは大変です。

なのでこの記事ではこの方法には深くは触れないことにします。

手軽さと自由度が高いObservable.Create

Observableのファクトリメソッドに、Observable.Create()というものがあります。
これを使うとある程度複雑なObservableも手軽に作ることができます。

Observable.Create<Unit>(observer => {

    // 任意のタイミングで通知する
    observer.OnNext(Unit.Default);
    observer.OnCompleted();
    observer.OnError(new Exception());

    return Disposable.Empty;
});

またこのファクトリメソッドはDisposableを返却するため、
このDisposableに破棄時の処理を書けばCompleteやError、Cancelした時の処理を記述することができます。

Observable.Create<Unit>(observer => {

    return Disposable.Create(() => {
        // Complete時 / Error時 / Cancel時に呼ばれる
        Debug.Log("Disposed");
    });
});

イベントからObservableを作るObservable.FromEvent

Observable.FromEvent()を使うとクリックイベントなどのイベントからObservableを作れます。

Action someAction = null;
Observable.FromEvent(h => someAction += h, h => someAction -= h);

上記の例では、これでsomeActionがInvokeされた際にストリームに値が流れてきます。

コルーチンからObservableを作るObservable.FromCoroutine

コルーチンをObservableに変換するにはObservable.FromCoroutine()を使います。
下記のように書くとコルーチンが終了した時にOnCompleteが呼ばれるストリームが作られます。

public void Start()
{
    Observable.FromCoroutine(ExampleCoroutine);
}

IEnumerator ExampleCoroutine()
{
    yield return new WaitForSeconds(1);
}

値の通知を行うにはIObservableを引数に取るコルーチンを定義します。

public void Start()
{
    Observable.FromCoroutine<Unit>(observer => ExampleCoroutine(observer));
}

IEnumerator ExampleCoroutine(IObserver<Unit> observer)
{
    yield return new WaitForSeconds(1);
    observer.OnNext(Unit.Default);
}

またこのようにコルーチンをObservable化すると、例外処理が書きやすくなるので便利です。

処理をサブスレッド化するObservable.ToAsyncとObservable.Start

Observable.ToAsync()を使うと引数に指定した処理をサブスレッドで処理します。
Invoke()を呼んだ時点から処理を開始します。

Observable.ToAsync(() => {}).Invoke();

またObservable.Start()を使うとObservable.ToAsync()のあとすぐInvoke()したのと同じ効果が得られます。

Observable.Start(() => {});

これらの使い方については下記の記事に詳しく記載していますので必要に応じて参照してください。

light11.hatenadiary.com

関連

light11.hatenadiary.com