ニートが学ぶUniRx 入門編その4

どうもこんばんは、UniRxを完全に理解したいニートです。
今回もとりすーぷさんの記事をもとに進めていく備忘録です。
https://qiita.com/toRisouP/items/30c576c7b0a99f41fb87

Updateを変換する方法

お題は「Update()をストリームに変換する方法」のようです。
Update()をストリームに変換すると何がよいのか全くわかりませんが、とりあえず進めてみます。

UpdateAsObservable

1つ目は拡張メソッドのUpdateAsObservableを使ってUpdateをストリームに変換する方法が紹介されています。
このメソッドはComponentクラスの拡張メソッドとして書かれていますので、MonoBehaviourを継承しているクラスなら当然使えます。
この拡張メソッドを呼び出したタイミングで、ObservableUpdateTriggerコンポーネントが勝手にアタッチされるみたいですね。
今のところフーンという感じで、これが何の役に立つのかいまいちピンときません。
というわけでお次。

Observable.EveryUpdate

2つ目はObservable.EveryUpdateです。
こちらはObservableUpdateTriggerコンポーネントが勝手にアタッチされることはないようです。
つまりUpdateAsObservable拡張メソッドとは根本的に違う処理で「Update()をストリームに変換」を実現していることを意味します。
最も大きな違いは、UpdateAsObservableはGameObjectがデストロイされたらストリームも一緒にDisposeされるのに対し、Observable.EveryUpdateは手動でDisposeする必要があることのようです。
これはGameObjectのコンポーネントとして動作しているか、シングルトンのオブジェクトとして動作しているかの違いが引き起こしている差異なのでしょうね。

その他の細かい違いはとりすーぷさんの記事を読んでもらえばよいんじゃないでしょーか。

使い分け

詳しい使い分け方はとりすーぷさんの記事を読んでもらうとして、僕はよほどの必要がない限りはUpdateAsObservable拡張メソッドを使用しようかなと思っています。
理由は単純で、僕がGCが勝手に掃除してくれる言語しか使ったことがないため、こういったオブジェクトの管理に慣れていないためです。
つまりヒューマンエラーでゲームが激重になったら困るからです。
ただMonoBehaviourを継承していないクラスでどうしてもUpdateを使いたいときはObservable.EveryUpdate()を使うしかないですかね……。
それでも何か別の代替手段を考えるかもしれませんが。

それでメリットはなんやねん

ようやく「Updateをストリーに変換するメリット」の項目に来ました。
例では「ボタンを押している間一定間隔で攻撃する」コードが扱われています。
これはよくあるシチュエーションですよね。
コードも眺めてみました(ThrottleFirstについては以下のURLを参考にしたらよくわかります)。
https://qiita.com/toRisouP/items/fe52e1582c14782af3ac

記事中のサンプルコードはZキーが押されたあと、次のOnNextをintervalSeconds秒待つという感じですかね。
つまりzキーを連打しても、intervalSeconds秒は反応しないということでしょう。
確かにこれはUniRxの読み方さえ知っていれば「ゲームロジックを宣言的に簡潔に記述することが可能」と言えるでしょう。

ThrottleFirst

今回の主題とは関係がないのですが、ThrottleFirstが便利そうだったので、僕も「タッチされても1秒間は反応しないオブジェクト」を作ってみました。
と言ってもめちゃんこ簡単です。コードはこんな感じ。

たったこれだけで「タッチされても1秒間は反応しないオブジェクト」が完成します。
素晴らしい!

移動・ジャンプ・着地効果音の再生をするロジックの例

UniRxを使わなかった場合と、UniRxを使った場合で「移動・ジャンプ・着地効果音の再生をするロジック」のサンプルコードが書かれています。
確かにUniRxを使ったほうが理解しやすいコードとなっています。
ただ僕は「移動用コンポーネント」「ジャンプ用コンポーネント」「効果音再生用コンポーネント」などとわけてコードを書くようにしています。
こうすると、UniRxを使わない場合でも例ほどは複雑になりません。
単一責任の原則を守るならば、UniRxを使う場合でもコンポーネントは分けた方がいいんじゃないかなあと思いました。

ObserveEveryValueChangedの補足

前回分の記事の補足として「ObserveEveryValueChanged」の正確な説明が付されています。
曰く「ObserveEveryValueChangedは監視対象のオブジェクトを弱参照(WeakReference)で参照」とのことです。
これはつまり、監視対象のオブジェクトがObserveEveryValueChanged以外から参照されなくなると、ガベージコレクションが対象オブジェクトを回収しようとするということを意味します。
回収時にOnCompletedも発行されるようです。
それだけですね。ちゃんちゃん。

終わりに

だんだんとわかるようになってきたUniRxです。
この調子でガンガンいきます。

ほなまた。

フォローする