sunagimoブログ

主にUnityに関する技術を取り上げます

【Unity】UniRxを覚える(2)

前回の記事。

sunagimo-app.hatenablog.com



ストリーム

UniRxを覚える(1)で学んだ、
Subjectを定義して、OnNextとして、Subscribeに到達
という流れをストリームと呼びます。


Dispose

IObservableのSubscribeはIDisposableというインターフェースで実装されています。
これはリソースの開放を行うためのもので、
Dispose()のみ定義されています。

SubjectでDisposeを実行すると、ストリームの購読を終了することができます。

    /// <summary>
    /// UniRx Subject。
    /// </summary>
    public Subject<string> subject = new Subject<string>();

    void Awake()
    {
        // UniRx Subject登録。
        subject
        .Subscribe(
            message => {
                Debug.Log(message);
            },
            () => {
                Debug.Log("Completed");
            }
        );
    }

    void Start()
    {
        // UniRx Subject呼び出し。
        subject.OnNext("UniRx Hello!");
        subject.Dispose();
        subject.OnNext("UniRx Hello!");
        subject.OnCompleted();
    }


Disposeのあとの処理は呼び出されません。


ストリームのライフサイクル

Subjectが破棄されればストリームも全て破棄されます。
Subjectが残っていればストリームは動き続けます。

ストリームは使い終わったら必ずDisposeを呼ぶ
またはOnCompletedを発行するようにする。

AddTo

AddToを実装すれば、GameObjectが破棄されたタイミングで、
自動的にDisposeを行ってくれます。

        // UniRx Subject登録。
        subject
        .Subscribe(
            message => {
                Debug.Log(message);
            },
            () => {
                Debug.Log("Completed");
            }
        ).AddTo(gameObject);


ストリームのソース

Subject

自由にイベントを発行したいとき。

ReactiveProperty

変数にSubjectの機能をくっつけたもの。

        var reactiveProperty = new ReactiveProperty<string>("sample");
        reactiveProperty.Value = "Hello";
        reactiveProperty.Subscribe(e => Debug.Log(e));
        reactiveProperty.Value = "hello";


ReactiveCollection

状態の変化を通知する機能が内蔵されたList< T >

        var reactiveCollection = new ReactiveCollection<int>();
        reactiveCollection
            .ObserveAdd()
            .Subscribe(x => {
                Debug.Log("Add Index: " + x.Index + " Value: " + x.Value);
            });
        
        reactiveCollection
            .ObserveRemove()
            .Subscribe(x => {
                Debug.Log("Remove Index:" + x.Index + " Value: " + x.Value);
            });

        reactiveCollection.Add(1);
        reactiveCollection.Add(2);
        reactiveCollection.Remove(2);


Observable.Create

自由に値を発行するストリームを作ることができるファクトリメソッド。

        Observable.Create<int>(ob => {
            ob.OnNext(1);
            ob.OnCompleted();
            return Disposable.Create(() => {});
        }).Subscribe(e => Debug.Log(e));


Observable.Start

別スレッドで実行して結果を一つだけ発行するファクトリメソッド。
非同期で走らせ結果が出たら通知。

        Observable.Start(() => {
            var count = 0;
            for(var idx = 0; idx < 10000; ++idx)
            {
                count += idx;
            }
            return count;   
        })
        .ObserveOnMainThread()
        .Subscribe(e => Debug.Log(e));
        Debug.Log("mainThread");

mainThreadの文字列が先に発行される。

Observable.Timer/TimerFrame

一定時間後にメッセージを発行するファクトリメソッド。
実時間はTimer、フレーム数での指定はTimerFrame

        Observable.Timer(System.TimeSpan.FromSeconds(3))
        .Subscribe(e => Debug.Log("elapsed 3sec"));

        Observable.Timer(System.TimeSpan.FromSeconds(3), System.TimeSpan.FromSeconds(1))
        .Subscribe(e => Debug.Log("elapsed 3sec and repeat 1sec"))
        .AddTo(gameObject);

第一引数に発行されるまでのTimeSpan、第二引数に繰り返し発行するTimeSpanを指定できる。

Observable.EveryUpdate

Update時に通知してくれるストリームソース。
停止しない限りシーンをまたいでも動き続けます。

        Observable.EveryUpdate().Subscribe(e => Debug.Log("every update"));



UniRx.Triggers

UnityのコールバックイベントをUniRxのIObservableに変換してくれる。

        this.FixedUpdateAsObservable()
            .Subscribe(e => Debug.Log("fixed update"));



uGUIイベントのストリームソース

クリックイベント

        [SerializeField]
        Button button = null;

        button.OnClickAsObservable().Subscribe(e => Debug.Log("onclick"));



(3)に続きます。
sunagimo-app.hatenablog.com




参考にさせていただいたサイト様

qiita.com


qiita.com