##00. この記事の目的
この記事の目的はUniRxを導入または学習を検討している方に軽く概要を掴んで頂いて検討材料にしていただければなと思い書き始めました。そのため、細かなUniRxの書き方等はこの記事に含まれていません。
##01. UniRxとは?
通常、UnityではReactive Extensions(以降Rx)は機能しません。そこで、Yoshifumi KawaiさんによりをUnity向けにRxの概念とさまざまなユーティリティを追加し、再実装しなおしたものがUniRxになります。それ故、Rxの概念を理解していることがUniRxを使用する上で非常に重要になってきます。
まとめ
・UniRx = unity + Reactive Extensions
##02. Rx(Reactive Extensions)とは?
①Rxの定義
Rxとは監視可能なシーケンスを使用して「非同期」「イベント」ベースのプログラム制作を目的として制作されたライブラリーで、Observerパターンと言うデザインパターンによって構成されています。
ここでよくある間違いについてですが、 Rxと関数型リアクティブプログラミング(functional reactive programming)が混同されることがよくありますがこれらは異なるものであるということに注意してください。Rxの公式サイトでもこのふたつの違いについて、「**関数型リアクティブプログラミングは時間の経過に伴い連続的に変化する値によって変化していくのに対して、Rxは時間の経過とともに放出される離散型の動きをする。」**と説明されており、二つが別のものであることを理解できます。
まとめ
・Rxは複雑な非同期処理やイベント処理、時間が関係する処理を、 LINQ形式で簡単かつ宣言的に記述できる。
・Reactive Extensions ≠ 関数型リアクティブプログラミング
##03. Observerパターンとは?
ObserverパターンはSubject(監視対象)とObserver(観測者)の2つの役割から成り、監視対象の状態が変化した際に観測者に通知されるデザインパターンのことを言い、状態変化に応じた処理を記述する際に好まれる書き方とされています。
Example:
オークションを例に挙げると観測者が入札者となり、競売人が監視対象となります。下記の図のように初めに13番の札を持つ人が入札した際Subjectの入札金額に変更が起こります(監視対象の状態変化)。次に入札金額の変更を競売人がオークション対象者に通知します(観測者への通知)。
(https://sourcemaking.com/design_patterns/observer)
ここまでで、ObserverパターンはObserverがSubjectを観察するものなんだと思った方もいると思うのですが、実際は
『Subjectが各Observerを管理する』というのが正しい認識になるので注意してください。
まとめ
・Observerパターンとは監視しているオブジェクトに発生するイベントについて複数のオブジェクトに通知するサブスクリプションメカニズムを定義できる動作設計パターン。
・Observerは受け身でSubjectがObserverへの参照をもつ。
##04. 結局UniRxって導入するべきなの?
UniRx導入を検討している方が一番気になるところはここだと思います、私もUniRxを勉強するにあたり色々な記事等を読みましたが、基本的に書かれている内容はUniRxの良い点がほとんどした。逆に疑いたくなるレベルでした、しかし、不安とは裏腹に少なくとも私にとってはUniRxは非常に便利なものでした。
###悪い点
悪い点① 学習コストが高い
私が読んだ記事にUniRxは学習コストが非常に高いと言った内容が書かれたものがありました。実際高いと言ったら高いのかも?抽象的な言い方だったのではっきり言うと、UniRx自体の学習コストは全く高くないです。しかし、一定数UniRxを勉強し始めた時に「難しくない?」「学習コスト高!!」と感じる人もいると思います。このように感じる人の原因は「C#のevent」「メッセージパッシング」「非同期処理」「unityのUpdate」「シーケンス(LINQ)」「Rx」について理解が足りていないことにあると思います。もし、どれかひとつでも当てはまるようでしたらページ最後におすすめのサイトのURLを添付してあるので確認してみてください。
悪い点② UniRxそのものが少し重いことによる弊害
UniRxは1フレームに一回しか呼ばれない処理や非同期処理(Ex.通信、IO)といった負荷の重くない処理を得意としています。一方、1フレームに何度もインスタンス(Observable)の生成が行われるといった負荷の重い処理での利用には向いていません。理由は単に処理が重くなり場合によっては動かなくなるからです。
悪い点②に関しては一応悪い点としてあげていますが、unityのUpdateでも同じことが言えるのでUniRxだけの問題ではないと思います。
###良い点
良い点① UniRxのオペレータによる従来のUpdateをストリーム化できる
UniRxにはさまざまなオペレーターが用意されているのですが、それらのオペレーターによりunity従来のUpdateをストリーム化しロジックを明確に処理することが可能になります。加えて、変数のスコープの明確化やロジック単位で分割し処理を行うことが可能になったり例外処理が統一されるといったメリットもあります。
良い点② 従来のイベントにはできなかったことが可能に
発生したイベントに関する値の変化を監視し対応することが容易(Observerパターン)になります。加えて、従来のイベントではdelegateの定義が必要とされていましたが、UniRxではそれが不要になります。もうひとつ、これをメリットと捉えるかは時と場合によるとは思うのですがUniRxは後発的な処理です。
良い点③ 時間処理が容易に
私自身特にUniRx便利だなと感じたのが時間に関する処理です。例えば、イベントの発火タイミングの処理や時間に伴い変化する値の監視や非同期処理です。非同期処理のおかげで実行スレッドを容易に変更したり、フレーム処理が本当に容易になります。
補足
UniRxではイベントの処理や時間処理の便利機能を総称として「Observable」と読んでいます。
###注意事項(チームプロジェクト向け)
UniRxを全員が理解していることを前提で話を進めますが、チームでUniRxを導入してプロジェクトを進める際、スパゲティプログラムには気をつけてください。もともとUniRx自体は可読性も高く、書き方が統一されるためテストが非常にしやすいといったメリットがあるのですが、UniRxの特徴でもあるStreamとSubscribeを走らせる場所にルールを設けないとチームプロジェクトでは著しく可読性が低下しテストもしにくくなることが予想できます。
##05. まとめ
私自身UniRxを勉強し始めた時はC#のイベントの理解とObserverパターンの利点について理解が甘くUniRxを勉強する前に周りみちをしました。UniRxの機能自体は便利なものが多く、わざわざUniRxで書かなくても良いのでは?という処理もありますがそれ以上にイベントや時間周りの便利機能のことを考えると導入した方が良いのではないかなと思います。特にunityのプログラミングレベルを上げたいと考えている方にはunityとC#の理解が深まるので是非とも学習を始めてほしいです。
##おすすめサイト
UniRxチュートリアル:
https://qiita.com/toRisouP/items/00b8a5bb8e7b68e0686c
Observerパターン(日本語):
https://blog.xin9le.net/entry/2011/12/10/153032
C#の機能について網羅しているサイト(イベント & 非同期処理 & シーケンス):
https://ufcpp.net/study/csharp/
メッセージパッキング:
http://itdoc.hitachi.co.jp/manuals/3000/30003D0820/GD080321.HTM#ID00763
Reactive Extensions:
https://atmarkit.itmedia.co.jp/fdotnet/introrx/introrx_01/introrx_01_01.html
Functional Reactive programmingとは?(英語QAですが内容は具体的に書いてあるためおすすめです。):
https://stackoverflow.com/questions/1028250/what-is-functional-reactive-programming/1030631#1030631