概要を確認した次はエントリポイントからの確認として Unity の Hierarchy から実装を見ていきます。
確認環境
- Unity 2019.3.7f1
- MRTK v2.4.0
Hierarchy の確認
まず、MRTKをインポートし、メニューの [Mixed Reality Toolkit] > [Add to Scene and Configure...]を選択します。 この時点ですでに最低限動作をする状態となっているため、Hierarchy を確認します。
この中で、MixedRealityToolkit の子にある複数の GameObject は UnityEditor 上でアクティブなサービスを可視化するために表示しているだけのもの(*1)なので、無視すると具体的に見る必要があるコンポーネントは以下の4つになります。
MixedRealityToolkit オブジェクト
- MixedRealityToolkit コンポーネント
- MixedRealityToolkit コンポーネント
Main Camera オブジェクト
- EventSystem コンポーネント
- MixedRealityInputModule コンポーネント
- GazeProvider コンポーネント
この4つのスクリプトを元にして MRTK は動作していることになります。 この中で、EventSystem は Unity の機能であり MRTK の実装ではありません。
また、MixedRealityInputModule は StandaloneInputModule を継承したもので EventSystem と一緒に用いて動作するものになるため uGUI を利用する際に必要なものとなります。
確認として MixedRealityInputModule コンポーネントを削除して PressableButtonHoloLens2 プレハブのボタンを配置してみても問題なく操作できます。(なお EventSystem は削除するとエラーがでます)
従って、uGUI はひとまず利用しない前提で考えると、MRTK の中身を把握していくためには、以下2つのコンポーネントを掘り下げていけば良いことになります。(たったの2つ!)
- MixedRealityToolkit コンポーネント
- GazeProvider コンポーネント
MixedRealityToolkit コンポーネント
概要
- Mixed Reality Toolkit の操作の調整を担当する
- プロジェクト全体で唯一のシングルトン(サービスロケーターパターンになっている)
- プロジェクト内で使用されるすべてのアクティブなサービスのサービスレジストリを提供する(サービスの登録・解除・取得を行う)とともに、プロジェクトのアクティブな構成プロファイルを提供する(プロファイルで設定した内容にどこからでもアクセスできる)
- プロファイルは、プロジェクトのニーズを満たすためにいつでも交換できる(ランタイムでの交換は現状未対応:ここの Note の欄に記載されている)
継承関係
次に、MonoBehaviour を継承したものなので イベント関数の実行順序 の順に追っていきます(終了関連の処理は省略)
実行順の動作確認
Awake()
- MixedRealityToolkitインスタンスを登録する(インスタンスを toolkitInstances リストへ追加する、マルチシーンの場合はMixedRealityToolkitインスタンスが複数になることがあるため)
- インスタンスの初期化処理を行う
- サービスロケーターの初期化(プロファイルに設定されているサービスをソートして登録)
- 登録したサービスをそれぞれ順番に初期化する(具体的な処理は対応するサービスに委譲)
OnEnable()
- プロファイルに設定されているサービスを順番に有効にする(具体的な処理は対応するサービスに委譲)
Start() なし
Update() / LateUpdate()
- プロファイルに設定されているサービスを順番に更新する(具体的な処理は対応するサービスに委譲)
GazeProvider コンポーネント
概要
- ゲイズの機能 (ヘッドと視線の両方) は、GazeProvider によって提供される
- 他の入力ソースと同様に、GazeProvider はポインターを使用してシーン内のオブジェクトとインタラクションする
- GazeProvider の場合、ポインターは InternalGazePointer によって実装され、プロファイルによって設定されていない
継承関係
実行順の動作確認
MixedRealityInputSystem 初期化の段階で、GazePointar へのアクセスがあるので、OnEnableよりも前に InitializeGazePointer メソッドが呼ばれ、ポインターの生成・初期化を行っている。またカーソルも生成される(InitializeGazePointerの中にブレークポイントを張って実行すると確認できる)。
Awake() なし
OnEnable()
- 親クラス(InputSystemGlobalHandlerListener) の OnEnable から RegisterHandlersメソッドが呼ばれ、GazeProviderのオーバーライドしたRegisterHandlersメソッドが呼ばれる
- RegisterHandlersメソッド で GazeProvider 自身を IMixedRealityInputHandler としてグローバルリスナーに登録する
- Input Up/Down をグローバルに受け取ることができるようになる
Start()
- OnEnable で InputSystem が取得できなかった場合は、改めて取得し RegisterHandlers メソッドを呼ぶ
- カーソルを表示する
- RaiseSourceDetected メソッドを呼び、ゲイズの入力ソースが検出されたときの処理を行う
Update()
- デバッグ用のレイ表示など
LateUpdate()
- 頭の速度(HeadVelocity)を更新
- 頭の移動方向(HeadMovementDirection)を更新
シーンの実行
次にシーンを実行してみたときの Hierarchy です。
以下のゲームオブジェクトが追加されています。
- Diagnostics(プロファイルでオンにしている場合)
- DefaultCursor(Clone)
- None_GGVPointer
- UIRaycastCamera
これらの GameObject は MixedRealityToolkit または GazeProvider (またはその中で新たに生成されたオブジェクトの中)で生成されていると言えます(*2)。
まとめ
MixedRealityToolkit コンポーネントがサービス全体のとりまとめをおこなっていることがわかりました。プロファイルで利用したいサービスの具象クラスを設定するようになっているので、さらに詳細を把握したい場合は、その具象クラスを追っていけば良いことがわかります。
(*1) プロファイルの Editor > Use Service Inspectors のコメントを見るとそう書かれており、チェックを外すと Hierarchy から GameObject も削除されます
(*2) 実際に生成されている場所は以下
DefaultCursor(Clone) :
- GazeProvider クラスの InitializeGazePointer メソッド
None_GGVPointer :
- BaseInputDeviceManager クラスの CreatePointer メソッド(具象クラスはUnityEditorで実行している場合はInputSimulationService)
- GGVPointer クラスの中で GameObject 名が "GGVPointer(Clone)" から "None_GGVPointer" に書き換えられている
UIRaycastCamera :
- FocusProvider クラスの FindOrCreateUiRaycastCamera メソッド