Unity

UniRxを使ってコードを見やすくする

UniRxとは

UniRxは、Reactive ExtensionsをUnity向けにカスタマイズしたライブラリです。

Reactive Extensions、略してRxは、MicrosoftResearchによって開発が行われた、C#向けのライブラリです。
GoFのデザインパターンの一つでもある、Observerパターンが軸となっています。

UniRxはUnity向けに作られたライブラリですが、Reactive Extensionsは他の言語にも移植されており、とても優れたライブラリになっています。

本物のReactive Extensionsに比べると、Unityに特化している、パフォーマンスが良くメモリが効率的に使われている、独自のReactivePropertyが追加されている、様々なオペレータが追加されている、などの特徴があります。

UniRxを使おうとした経緯

UniRxを使おうとした経緯ですが、ファイル操作、通信処理、UIの記述などを行う際、冗長的な書き方になってしまうことが多かった為、なんとかもう少し簡潔にできないだろうか、というところからUniRxにたどり着きました。

Subject

SubjectというものがUniRxを使う上で、重要なものになってきます。

その中でもさらに重要な概念として、Subscribeと、OnNextというものが存在します。

Subscribe

メッセージを受信した際に実行される処理を登録する。

OnNext

何かの値(メッセージ)をSubscribeが行われた際に渡す。

具体的な例は以下に記載します。

コード

Subject sub = new Subject();

sub.Subscribe(message => Debug.Log("A:" + message));
sub.Subscribe(message => Debug.Log("B:" + message));
sub.Subscribe(message => Debug.Log("C:" + message));

sub.OnNext("Message1");
sub.OnNext("Message2");

実行結果

A:Message1
B:Message1
C:Message1
A:Message2
B:Message2
C:Message2

IObservable、IObserver

先述したSubjectはIObservableインターフェースとIObserverインターフェースを実装しています。

IObservable

IObservableインターフェースは、イベントメッセージを購読できるインターフェースです。
内容としてはSubscribeメソッドが定義されています。

IObserver

IObserverインターフェースは、イベントメッセージを発行できるインターフェースです。
内容としてはOnCompleted、OnError、OnNextの3つのメソッドが定義されています。

上記のことからSubjectは、値を発行でき、かつ、値を購読できる、ということが言えます。

オペレーター

UniRxを使う上でかかせないのがオペレーターの存在です。

よく使用する頻度の高いものを少し紹介します。

Where

こちらはメッセージをフィルタリングするオペレーターになります。
使用例を以下に記載します。

“Message1″という文字がきたときのみ処理を行いたい場合

Subject sub = new Subject();

sub.Where(message => message == "Message1")
   .Subscribe(message => Debug.Log("A:" + message));

sub.OnNext("Message1");

これをWhereを使わないで書くと、if文で分岐をしなくてもいけなくなります。
以下、例です。

Subject sub = new Subject();

sub.Subscribe(message => {
    if(message == "Message1") {
        Debug.Log("A:" + message);
    }
}
);
sub.OnNext("Message1");

Whereを使ったほうがスッキリしているのが分かると思います。

uGUIをUniRxで管理する

UniRxを使うメリットの中でもとくにコードがスッキリするのがuGUIのボタンなどをRx化することではないかと思います。

Inspectorからボタンに関数を登録することもできますが、これだとScriptを見ただけではどの関数が呼ばれるのか分からない為、処理が追いにくいです。

そこでserializefieldにしたボタンをRx化して、処理を記述した方が、直感的に何をしたいのかがわかります。

以下に例を記載します。

[SerializeField]
private Button _button;

void Awake() {
    _button.OnClickAsObservable()
           .Subscribe(_ => {
               // ここに処理を書いたり、関数を呼んだりします
           });
}

ただ、注意しなければならないのが、このままだとストリームが破棄されません。

ストリームを破棄する為にはDisposeをする必要があるのですが、いちいちその処理を書くのが面倒という場合には便利な書き方があります。

それはAddToです。

AddToはUniRxに用意されているメソッドで、Subscribeの後に書くことで、対象のGameObject(Button)が破棄(Destroy)されたタイミングで、自動的にDisposeを実行してくれます。

便利なので忘れずに記述するようにした方がいいです。
ストリームが残ったままだとメモリリークの原因になります。

AddToは以下のように記載します。

[SerializeField]
private Button _button;

void Awake() {
    _button.OnClickAsObservable()
           .Subscribe(_ => {
               // ここに処理を書いたり、関数を呼んだりします
           }).AddTo(this.gameObject);
}

関連記事

  1. Unity

    Behave 2 for Unityを使ってみた

    Behave 2 for UnityとはBehaviour Tre…

  2. Unity

    【中途採用】Unityエンジニアの転職先としてオススメする会社5選

    Unityエンジニアの需要ゲーム制作ツールとして不動の地位を築いた…

  3. Unity

    UnityIAPを導入するにあたり、つまずいた点

    UnityIAP(In App Purchase)はUnity5.3の…

  4. Unity

    UnityでUIをタップした際に、奥のWorld上のオブジェクトが反応しないようにする方法

    UnityでuGUIで作成したButtonをタップした際に奥にあるオブ…

  5. Unity

    GTMF 2018東京に行ってきたのでまとめてみる

    7月13日(金)に行われたGTMF2018東京に行ってきました。公…

コメント

  1. この記事へのコメントはありません。

  1. この記事へのトラックバックはありません。

カテゴリー

最近の記事

  1. Unity

    【中途採用】Unityエンジニアの転職先としてオススメする会社5選
  2. Unity

    Behave 2 for Unityを使ってみた
  3. Unity

    GTMF 2018東京に行ってきたのでまとめてみる
  4. Unity

    UnityIAPを導入するにあたり、つまずいた点
  5. Unity

    UnityでUIをタップした際に、奥のWorld上のオブジェクトが反応しないよう…
PAGE TOP