sunagimoブログ

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

【Unity】UniRxを覚える(1)

UniRxとは


C#のライブラリのReactive ExtensionsをUnity向けに作られたライブラリ
デザインパターンの一つのObserverパターンがベースになっています。


Subject


UniRxにおいて、重要なもの。
Subjectがこれまで使ってきた、eventの役割になる。


そしてSubjectの中でも重要な2つの処理が、
SubscribeとOnNext。

Subscribe

メッセージ受取時に実行する処理を登録

OnNext

Subscribeに登録された処理に渡して処理を実行


Subject、Subscribe、OnNextの処理を今までのイベント処理で書くとこんな感じになる。


UniRx実装前

    /// <summary>
    /// イベント。
    /// </summary>
    /// <param name="message">メッセージ。</param>
    public event Action<string> OnDisplayMessage = delegate(string message){};

    void Awake()
    {
        // 登録。
        OnDisplayMessage += (message) => {
            Debug.Log(message);
        };
    }

    void Start()
    {
        // 呼び出し。
        OnDisplayMessage("Hello!");
    }



UniRxを使うとこのように書き直せる。

UniRx実装後

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

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

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




IObserverとIObservable


SubjectはIObserverとIObservableの2つのインターフェースを実装しています。

IObserver

イベントメッセージの発行を担う

OnCompleted
OnError
OnNext

の3つのメソッドが定義されている。

IObservable

イベントメッセージを購読を担う

Subscribe
のメソッドが定義されている。


先程の処理に、OnNext、OnError、OnCompletedを追加するとこのように定義できる。

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

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

            error => {
                Debug.LogError("Error");
            },

            () => {
                Debug.Log("Completed");
            }
        );
    }

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



オペレータ


SubjectとSubscribeの間に挟み込んでメッセージを処理する部品のこと。
LINQのWhereオペレータみたいなもの。

    /// <summary>
    /// Linqサンプル。
    /// </summary>
    public List<int> linqSampleList = new List<int>();

    void Awake()
    {
        linqSampleList.Add(1);
        linqSampleList.Add(2);
        linqSampleList.Add(3);
        linqSampleList.Add(4);
    }

    void Start()
    {
        var resultList = linqSampleList.Where(e => e % 2 == 0).ToList();
        for(var idx = 0; idx < resultList.Count; ++idx)
        {
            Debug.Log(resultList[idx]);
        }
    }


UniRxの代表的なオペレータ

Where:フィルタリング
Select:メッセージを変換
Distinct:重複を排除
Buffer:一定個数をまとめるまで待つ
ThrottleFirst:短時間にまとめてきた場合に先頭のみを使う

LINQライクな書き方


Whereを使用する

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

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

            error => {
                Debug.LogError("Error");
            },

            () => {
                Debug.Log("Completed");
            }
        );
    }

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



"UniRx Hello!"のみ出力される


AwakeやStartへの負担が気になる…


続き
sunagimo-app.hatenablog.com




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


qiita.com