【Unity】【UniRx】Subjectの概要と色んなSubjectの使い方

UniRxのSubjectとその使い方についてです。

Subject?

Subjectとは、IObservableとIObserverを実装したクラスです。

まずIObservableを実装しているのでSubscribe()で値の変化を監視できます。

Subject<Unit> subject;
subject.Subscribe();

また、IObserverを実装しているのでOnNext()、OnCompleted()、OnError()を呼べます。

Subject<Unit> subject;
subject.OnNext(Unit.Default);
subject.OnCompleted();
subject.OnError(new System.Exception());

外側からOnNext()とかを呼べる特殊なObservableだと捉えることができそうです。

使い方

例えば次のようにすると、ボタンがクリックされたことを通知するObservableを簡単に実装できます。

using UniRx;

public class Example {

    public Subject<Unit> buttonClickSubject  = new Subject<Unit>();

    private void OnClickButton()
    {
        buttonClickSubject.OnNext(Unit.Default);
    }

}

Subjectの種類

Subjectにはいくつか種類があるためそれぞれの特徴を紹介します。

名前 特徴
Subject OnNext()が呼ばれるたびに値を通知する
Subscribe()時は何も通知しない
ReplaySubject OnNext()が呼ばれるたびに値を通知する
Subscribe()時にそれまでにOnNext()でされた値をすべて通知
OnCompleted()後にSubscribe()すると全てのOnNext()とOnCompleted()が呼ばれる
BehaviourSubject OnNext()が呼ばれるたびに値を通知する
Subscribe()時に直近のOnNext()の値を通知
OnCompleted()後にSubscribe()するとOnCompleted()のみ呼ばれる
AsyncSubject OnNext()が呼ばれても値を通知しない
Subscribe()時は何も通知しない
OnCompleted()の際に同時にOnNext()を呼び、直近のOnNext()の値を通知
OnCompleted()後にSubscribe()するとOnNext()とOnCompleted()が呼ばれる

特殊なSubjectの使いどころ

BehaviourSubjectは、トグルボタンのクリックを監視し、OnNext()でトグルの状態を通知したいときなどに使えそうです。

using UniRx;

public class UniRxExample {

    public BehaviorSubject<bool> toggleButtonClickSubject   = new BehaviorSubject<bool>(false);

    private void Main()
    {
        toggleButtonClickSubject.Subscribe
        (
            toggled => 
            {
                // トグルの状態を使った何らかの処理
                // SubScribe時にも通知される
            }
        );
    }
}

AsyncSubjectはOnCompleted()後も最後のOnNext()がくるという特徴があるため、
ロード処理などに使える感じでしょうか。

using UniRx;
using UnityEngine;

public class UniRxExample {

    public AsyncSubject<Texture> loadSubject = new AsyncSubject<Texture>();

    private void Main()
    {
        // ロード完了時にこれを呼ぶ
        // これ以降にSubscribeした場合でもロードされたテクスチャが取得できる
        loadSubject.OnNext(texture);
        loadSubject.OnCompleted();
    }
}

ReplySubjectはどんなケースで使うのでしょうか・・ちょっとパッと思い浮かびません。

参考サイト

qiita.com

blog.xin9le.net