従来の HTK では各種入力や SpatialMap などには,シングルンクラスを通してアクセスしていましたが,以下のメリットより,MRTK v2 からは,サービスロケータパターンを採用することになりました。
- パフォーマンス:MonoBehaviourシングルトンが減って,更新速度が約80%向上。GameObjectがシーン にいらなくなった。
- 参照しやすさ:GameObjectをFindするコストがなくなって検出が早く簡単になった。
- 型依存しない:具体的な実装を利用側は気にする必要がなく,差し替えやすい。
- マルチシーンで利用:複数シーンにまたがってもサービスを利用するのが簡単
サービスロケータについては,実装も踏まえたこちらが分かり安いかと思います。 Zenject入門その1 疎結合とDI Container - Qiita
ただ,やはり型依存しないといってもサービスロケータの仕組み上,サービスロケータそのものに依存してしまう作りになってしまう点には注意が必要です。Dependency Injection の採用も検討はされていましたが,ユーザの使い勝手を考慮してサービスロケータが優先されたそうです。(とどこかでみた)
実際に使うには次のようにアクセスします。如何にもサービスロケータっぽい書き方ですね。IMixedRealityInputSystem をキーに,登録されているオブジェクトを引っ張ってくるイメージです。(参照を見る限り,返ってくるクラスは常に MixedRealityInputSystem です。)
var inputSystem = MixedRealityToolkit.Instance.GetService<IMixedRealityInputSystem>();
ただ,何にアクセスできるかが分かりづらいのでCoreServicesというユーティリティクラスも用意されています。 CoreServicesには,MRTKで登録されている基本的なサービスへのGetterが用意されています。現在CoreServicesからアクセスできるサービスは以下の通りです。
- InputSystem
- BoundarySystem
- SpatialAwarenessSystem
- TeleportSystem
- DiagnosticsSystem
- CameraSystem
- SceneSystem
使い方は先より簡単です。内部的には,MixedRealityToolkit.Instance へ問い合わせしています。
var inputSystem = CoreServices.InputSystem;
サービスロケータは慣れてしまえば別にどうってことはないですが,v1 の Singleton Manager クラスに慣れ親しんだ人は使いづらく感じるかもしれません。
また,リリースされたMRTKのExperimental機能のService Manager という少々ややこしい存在もいます。 MRTKはこれらを集約するシステムでしたが,こちらは個別にPrefabを置いて,Profileを設定していく方式になります。今までのHogeHogeManagerに近しい存在ですが,中を見る限り,それぞれがサービスロケータとして実装されているようです。
特にシングルトンクラスとして作られている訳でなく,各種サービスアクセスのためのUtilityもないので使うとしたらこんな感じでしょうか。
var inputSystem = GameObject.FindObjectOfType<InputSystemManager>().GetService<IMixedRealityInputSystem>();
Prefabを置くということはそれだけGameObjectを置くことになるので,前述のパフォーマンスから考えてもあまり旨味がなさそうな機能です。