はじめに
Unityの開発ではいろいろと便利なアセットが公開されていますが、そのうちUniRx, Zenjectについて理解を深めておこうと思いました。
わかってはいましたが、これが非常に奥が深く…これはとにかく使ってみないとわからんと思い至り、表題の内容で実際に使ってみたのでその記録を残しておきます。
(個人的な備忘録・頭の整理の側面が強いです)
環境
- Unity : 2019.3.0f6 64bit
- UniRx : 6.2.2
- Zenject(Extenject) : 9.1.0
書いた内容
- やろうとしたこと
- やってみたこと
- Zenjectを用いた動的な入力方法切り替え
- UniRxを用いた各種操作の監視
- まとめ
やろうとしたこと
とりあえずこんな感じのシーンをえいやと描いて、自機(真ん中の紙飛行機)を左右に動かしてみようと思いました。
自機を動かす入力方法を以下のように切り分けます。
・Android/iOS端末では画面のボタンで操作
・PCなどではキーボードの左右キーで操作
やってみたこと
Zenjectを用いた動的な入力方法切り替え
何はともあれ(?)以下の記事を何度も読んで、Zenject(今はExtenject)の導入に限らず疎結合な設計とインターフェースについて知見を得ました。
参考:Zenject入門その1 疎結合とDI Container
今回自分がやろうとしていることに当てはめるとこんな感じになりそうです。
・Playerは左右に移動するだけなのでIInputProviderに用意するIFはGetMoveのみ
・タッチ入力とキーボード入力を担当するInputProviderについて環境に応じたものをBindする(Zenject)
上記に追加で調べて対応した内容としては
・同じ型のButton2つをBindする際はIDを指定すれば別々にBindできる
・Monovihaviourでなくてよいクラスは継承を外し、コンストラクタで参照先をBindする
といった点がありました。
コンストラクタインジェクションだと[Inject]
アトリビュートおよびusing Zenject;
が不要なので、Zenjectなしの環境に対する可搬性が高いです。
(ただしID指定している場合は[Inject(Id = xxx)]
表記が必要…)
これでやりたいことはだいたい実現できますが、個人的に少し気になった点がありました。それはPlayerが毎フレーム(Updateのたびに)「そのフレームで左右移動の操作がされているか」をGetしに行くという構図です。
このような構図は様々なところで目にしますが、個人的にPlayerがUpdate関数でポーリングするのではなく、各種操作が実行された際にPlayerを動かすというイベントドリブンな構成にもしてみたいと思いました。
UniRxを用いた各種操作の監視
前述のZenject入門記事を書かれたtorisoupさんのスライドで紹介されている内容を参考に、自分もMVPモデルを意識して構成を見直しました。
・Presenter新規追加
・uGUIボタン・キーボード操作をPresenterが監視し、操作があったらPlayerに反映する
・各種入力および操作はUniRxの仕組みでSubscribeすることで監視下に入る
・InputProviderおよびPlayerはPresenterを参照しない
・Presenterは各種入力およびPlayerを参照する この参照にDIを用いる
前の構成ではIInputProviderというinterfaceがあり、いい感じに動的なBindがされていたのですが…
今回の構成ではInputProvider側で公開するのがIObservableプロパティでありメソッドではないのでinterfaceにできず、Baseクラスという位置づけにしました。
[2020/8/2訂正]
interfaceはプロパティを持つことができるのでIInputProviderのままで実装できました。
あとはクラス図の構成で実装を進め、ZenjectのScene ContextとInstallerを作成して(すみませんこのあたりの詳細は割愛)動作確認です。
※Editorですが画像取得のためuGUI入力有効にしてあります
よかった動きました(^^)それにしてもシンプルな…
ソースコードなどはGithubに置いてあります:
https://github.com/zeffy1014/Unity_InputPractice
まとめ
今回の一連の学習では
- UniRxによる各種操作の監視
- Zenjectによる動的な監視対象の紐づけ
について軽くかじって咀嚼・消化することができたかなあと思います。幸いアレルギーは出なかったので、この辺りを足がかりにUniRX, Zenjectの他機能についても使えるようになれればと考えています。
ただ注意すべきは、UniRxやZenjectを使うことが目的になってはいけないということで。
何よりもまずはよりよい設計を意識し、それでUniRxやZenjectが必要になったら使うのだぞということを常に頭に置いておこうと思います。
以上です。