Mixed Reality Toolkit - vNEXTの構造を理解する ～ Unity Etidorとプロジェクト構成編 ～

# Mixed Reality Toolkitの次期構想がついに形に
Mixed Reality Toolkitはライブラリとしては現状Ver.1としてHoloLens/Windows Mixed Reality両対応を目指したものとなっています。このライブラリの次のバージョンとして検討されているのがvNEXTと呼称される[Mixed Reality Toolkit vNext Alpha v2018.7.0.0](https://github.com/Microsoft/MixedRealityToolkit-Unity/releases/tag/2018.7.0.0-vNextAlpha)です。vNEXTは全てのxR関連デバイスでの開発を実現するコンセプトとなっており、α版が公開されています。

## 重要なこと
<font color="red">α版なので正式リリース前には大幅に情報が変わる可能性があります。</font>特に実装機能がまだイベント周りが中心です。現在はアーキテクチャ構造などを検討している段階だと考えられます。

## 関連情報
現在公開されているα版は以下のGitに公開されています。

* [Mixed Reality Toolkit vNext Alpha v2018.7.0.0](https://github.com/Microsoft/MixedRealityToolkit-Unity/releases/tag/2018.7.0.0-vNextAlpha)

過去vNEXTの情報が公開された時のコンセプトについては以下に整理しています。

* [Mixed Reality Toolkit - Unityの次期バージョンvNextのコンセプト](https://qiita.com/miyaura/items/b702cfe19163e9dac067)

今回調査した感じではコンセプト通りの構成になっています。

## vNEXTについて

vNEXTについてはコンセプトを見てもらえばわかると思いますが、基本的には現行バージョンとアーキテクチャ構造が大きく変わります。OpenVRやOculusなどのHoloLensやWinMR以外のデバイス対応も想定しているため各モジュールが入れ替え可能なDI的な要素になっています。今のところ分割途中といった感じで徐々にリファクタリングされていく形ですね。

![vNExt_Architecture](https://camo.qiitausercontent.com/9fd7c2adfca4fbc1f05a909e8b719fb1bbd2c4d5/68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f3135323534382f65313330303862392d363361302d356463302d656130632d6261346435383031653935662e706e67)

旧バージョンとの互換性はあまりないかもしれません。ただ、おそらくそれほどコードの移植に困ることは少ないと思います。
今回はUnity上でどう変わっているのか調べた内容が中心に公開したいと思います。
内部構造については順次公開していく予定です。
MRTK-vNEXTとして大きな変更点は以下の4点です。

* Unity Editor用のプロジェクト構成
* MRTKのコンポーネントの使い方が変更
* IL2CPP前提の設計（またUWP関連は考えることが増えた。。。）
* 内部アーキテクチャ構造の変更


### Unity Editor用のプロジェクト構成
以前は1プロジェクト(Editor用を含めると2プロジェクト)で構成されていたC#プロジェクトですが以下の構成に分割されています。ただ、今のところという印象。実際のリリース時にはもう少しプロジェクトが増えると思います。

![MRTK_Project.png](https://qiita-image-store.s3.amazonaws.com/0/152548/f6d0203d-42c7-5767-7391-043c573c81ef.png)

α版におけるプロジェクト構成は上記のような構造になっています。
コンセプトに従った場合、基本的にこれらのプロジェクトは修正不要でInspector内で設定を行うのみとなるはずです。仮に手を入れるとしても以下の順で修正すべき構造です。より下層に行くほどデバイス寄りの実装になります。

1. Microsoft.MixedReality.Toolkit.SDK.Player
2. Microsoft.MixedReality.Toolkit.InputSystem.Player
3. Microsoft.MixedReality.Toolkit.Player

なお、現状はリファクタリングも兼ねて進めているようなので[Microsoft.MixedReality.Toolkit]がもういくつかに分割されることになると思います。

#### 機能系プロジェクト
| プロジェクト名 | 主な機能 |
|:-:|:-:|
|Microsoft.MixedReality.Toolkit|現状のメインプロジェクトです。上記のアーキテクチャでMRTK-Constructsに相当する機能が含まれています。|
|Microsoft.MixedReality.Toolkit.Player|IL2CPP向けのUWP用プロジェクト。含まれるコードは「Microsoft.MixedReality.Toolkit」と同じです。コードを修正する場合はこのプロジェクト内のコードを変更します。このプロジェクトはUWPのインテリセンスが使えます。|
|Microsoft.MixedReality.Toolkit.Examples|MTRKのサンプルプロジェクトです。現在はα版で動作する旧版のサンプルが含まれています。|
|Microsoft.MixedReality.Toolkit.Examples.Player|IL2CPP向けのUWP用プロジェクト。含まれるコードは「Microsoft.MixedReality.Toolkit.Examples」と同じです。コードを修正する場合はこのプロジェクト内のコードを変更します。このプロジェクトはUWPのインテリセンスが使えます。|
|Microsoft.MixedReality.Toolkit.InputSystem|上記のアーキテクチャでMRTK Interface Layerに相当するプロジェクト。現在は各種デバイスの入力系（ジェスチャー、コントローラ）の検出とイベント制御に関する機能が含まれています。|
|Microsoft.MixedReality.Toolkit.InputSystem.Player|IL2CPP向けのUWP用プロジェクト。含まれるコードは「Microsoft.MixedReality.Toolkit.InputSystem」と同じです。コードを修正する場合はこのプロジェクト内のコードを変更します。このプロジェクトはUWPのインテリセンスが使えます。|
|Microsoft.MixedReality.Toolkit.Internal.Build|各種デバイスのビルドに関する機能を持つプロジェクト。以前はアーキテクチャ構造には出てきていなかったですが、プラットフォーム毎にビルド方法に違いがあるためその対応策として用意されていると考えられます。 |
||Microsoft.MixedReality.Toolkit.SDK|アーキテクチャ構造でMRTK User Abstraction Layerに相当する機能が含まれています。各レイヤー構成に合ったプロファイルの設定と呼出に必要な機能部品で構成されています。|
|Microsoft.MixedReality.Toolkit.SDK.Player|IL2CPP向けのUWP用プロジェクト。含まれるコードは「Microsoft.MixedReality.Toolkit.SDK」と同じです。コードを修正する場合はこのプロジェクト内のコードを変更します。このプロジェクトはUWPのインテリセンスが使えます。|

以下のプロジェクトは各機能に対するEditorのプロジェクトになります。Inspectorでの設定を支援するための部品群ですね。以前はすべてまとまったプロジェクトで管理されていたものを分割管理に変更したようです。

#### Editor系プロジェクト
各コンポーネントで設定するEditorの定義が含まれるプロジェクトです。

| プロジェクト名 | 
|:-:|
|Microsoft.MixedReality.Toolkit.Internal.Extensions.EditorClassExtensions|
|Microsoft.MixedReality.Toolkit.Internal.Utilities.Editor|
|Microsoft.MixedReality.Toolkit.Examples.Demos.StandardShader.Inspectors|
|Microsoft.MixedReality.Toolkit.InputSystem.Inspectors|
|Microsoft.MixedReality.Toolkit.Internal.Inspectors|
|Microsoft.MixedReality.Toolkit.Internal.Utilities.Editor.Setup|
|Microsoft.MixedReality.Toolkit.SDK.Inspectors|

#### ライブラリテスト用
ライブラリのテスト用プロジェクトです。

| プロジェクト名 | 
|:-:|
|Microsoft.MixedReality.Toolkit.Tests|

### MRTKのコンポーネントの使い方が変更

Unity上で使用するコンポーネント系はかなり使い方が変わりそうです。以下はサンプルのシーンを読込んだ状態でのHierarchyとProjectの構成になります。MRTKに必要な設定関連は1つに集約されており、これを各デバイスや作りに応じて切り替えることで全体を動かせるシステムに変更されています。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/152548/10e50592-b41e-2c14-0e93-c3aae303b1b2.png)

#### 必須コンポーネント
Hierarchyで必須になるコンポーネントが少し変わっています。ポイントになるのは以下の2つのオブジェクトになります。

* MixedRealityManager
* Body

##### MixedRealityManager
vNEXTでの動作環境や各種パラメータの定義を行うためのコンポーネントです。設定は上記のハードコピーにようにInspectorから色々設定が可能な形で整理されています。
設定値はある程度の機能単位で分割されています。

| プロファイル名 | 概要 |
|:-:|:-:|
| MixedRealityConfigurationProfile  | MRTKのためのメインの設定プロファイルです。MRTK全体の機能を構成するための設定と各機能に対するプロファイルの定義を行います。|
| MixedRealityInputActionsProfile  | 入力のアクションに対するプロファイルの定義を行います。ここで扱う入力とはコントローラの各種ボタンや位置や回転などです。これら入力の情報の取得に関する制約を設定します。例えば、モーションコントローラのSelectボタンは0～1の連続値ですが、これを連続値で扱うからデジタル値(0 or 1)で扱うかを定義することができます。  |
| MixedRealityControllerConfigurationProfile  | 入力装置であるコントローラに対する設定プロファイルです。アプリケーション内で利用する入力装置となるコントローラの定義と操作のマッピングを行います。それぞれの入力装置の具体的な動作は各SDKにゆだねられておりここでは[MixedRealityInputActionsProfile]で定義したアクションとコントローラのキーマッピングを行うことで所定の動作を実行できるようになります。|
| MixedRealityCameraProfile  | おなじみカメラに関する設定です。これは現行のMRTKの[Mixed Reality Camera Manager]で行う設定と同じものになります。|
| MixedRealitySpeechCommandsProfile  |  音声コマンドを定義するためのプロファイルです。 音声コマンドで認識するキーワードおよび、キーコードと[MixedRealityInputActionsProfile]とのマッピングを行います。|

###### MixedRealityConfigurationProfile

MRTKのためのメインの設定プロファイルです。MRTK全体の機能を構成するための設定と各機能に対するプロファイルの定義を行います。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/152548/d1066886-4e3c-79e6-d5b6-33b8c11ef07a.png)

| プロパティ名 | 説明 |設定値|
|:-:|:--|:--|
| Target Scale  |アプリケーションの利用環境を定義します。例えば[Room]では、屋内利用となり移動範囲を表示するためのBoundaryの機能が有効化されるなどです。利用シーンに応じて機能概要が設定できるようになっています。設定できる値は利用者の状態により[オリエンテーションのみ]、[座った状態]、[立った状態]、[屋内]、[現実空間]の6つになります。[屋内][現実空間]の2つは利用者がアプリケーション内で徒歩等での移動を前提にした設定になるようです。|<ul><li>Orientation Only</li><li>Seated</li><li>Stainding</li><li>Room</li><li>World</li></ul>|
| Enable Camera Profile|カメラ用プロファイルの設定について有効/無効を設定します。これはHoloLensやWindows Mixed Reality Deviceの切替えのようにカメラ独自のプロパティ制御を行う必要がある場合にチェックする形になると考えられます。|true/false   |
| Camera Profile  |カメラ用のプロファイル設定選択します。|DefaultMixedRealityCameraProfile|
| Enable Input System  |入力系のシステムの利用について有効/無効を設定します。|true/false|
| Input System Type  |入力系システムのタイプを設定します。|MixedRealityInputManager|
| Input Actions Profile  |入力系システムのアクションに対するプロファイルを設定します。(詳細は[MixedRealityInputActionsProfile](###### MixedRealityInputActionsProfile)参照)|DefaultMixedRealityInputActionsProfile |
| Pointer Profile  | ゲイズやコントローラのフォーカスを示すポインターに関するプロファイルを設定します。(詳細は[MixedRealityInputPointerProfile](###### MixedRealityInputPointerProfile)参照)  |DefaultMixedRealityInputPointerProfile|
|  Enable Speech Commands |音声コマンド入力について有効/無効を設定します。|true/false|
|  Speech Commands Profile |音声コマンド入力についてのプロファイルを設定します。音声コマンドに使用するキーワードやショートカットなどが設定可能です。(詳細は[MixedRealitySpeechCommandsProfile](###### MixedRealitySpeechCommandsProfile)参照) | DefaultMixedRealitySpeechCommandsProfile |
|Enable Controller Mapping|各xRデバイスで利用できるコントローラやジェスチャーに関するプロファイルの有効/無効を設定します。|true/false|
|Controller Mapping Profile|コントローラのマッピングを定義するプロファイルを設定します。このプロファイルではボタン操作に対してアクションを起こすかなどのマッピングを定義します。(詳細は[MixedRealityControllerConfigurationProfile](######　MixedRealityControllerConfigurationProfile)参照) |DefaultMixedRealityControllerConfigurationProfile|
|Enable Boundary System|Boundary Systemの有効/無効を設定します。これは屋内などの移動範囲を可視化するための境界表示に関するシステムです。Windows Mixed Reality Deviceにもあった機能ですね。|true/false|
|Boundary System Type|Boundary Systemのタイプを設定します。|MixedRealityBoundaryManager|
|Boundary Height|Boundaryの高さを設定します。いわゆる壁の高さですね。|3|
|Boundary Visualization Profile|Boundary Systemの見た目に関するプロファイルを設定します。境界面の色などを定義します。(詳細は[MixedRealityBoundaryVisualizationProfile](######　MixedRealityBoundaryVisualizationProfile)参照) |DefaultMixedRealityBoundaryVisualizationProfile|
|Enable Teleport System|Teleport Systemの有効/無効を設定します。これはWindows Mixed Realityのモーションコントローラで移動をする際に使う機能です（例：スティックで移動先のマーカーを出して移動したり方向転換）。|true/false|
|Teleport System Type|Teleport Systemのタイプを設定します。|MixedRealityteleportManager|
|Teleport Duration|テレポートの移動量を設定します。|0.25|

###### MixedRealityCameraProfile
おなじみカメラに関する設定です。これは現行のMRTKの[Mixed Reality Camera Manager]で行う設定と同じものになります。[Opaque Display Settings]が没入型xRデバイスの設定、[Transparent Display Settings]が透過型のデバイスの設定です。設定自体はUnityのCameraコンポーネントにある同種の設定と同じものです。動作時にMRTKがこの設定に応じて値を設定してくれます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/152548/3e70ba75-b859-32d1-ce29-82412853d060.png)

###### MixedRealityInputActionsProfile
入力のアクションに対するプロファイルの定義を行います。コントローラのボタン操作等をアクションとそれに対する制約として定義します。制約についてはアクションに対して取得できる値についての定義を行います。例えば、[Select]の場合は[Digital]となっていますが、これは0,1つまり押す/離すという制約をかけていることができるようです。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/152548/161baaa9-e2b1-d9be-8dae-5db3dc66cd71.png)

| プロパティ名 | 説明 | 設定値 |
|:-:|:--|:--|
| Action  | アプリケーション内で使用するアクションを定義します。 | 文字列（任意？)  |
| Action Constraint  | アクションの制約を定義します。 |<ul><li>None</li><li>Raw</li><li>Digital</li><li>Single Axis</li><li>Dual Axis</li><li>Three Dof Position</li><li>Three Dof Rotation</li><li>Six Dof</li></ul>|

###### MixedRealityInputPointerProfile

モーションコントローラやゲイズのポインターに関するプロファイルを定義します。複数登録することができ、初期設定はゲイズとコントローラの設定例になっているようです。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/152548/15e73bba-afa1-e8c8-424a-595844e124db.png)

| プロパティ名 | 説明 | 設定値 |
|:-:|:--|:--|
| Controller Type| コントローラのタイプを設定します。すでにxRデバイス用の実装がいくつか入っています（動くかは見ていないですが）。例えばWinMRやHoloLensの場合は[WindowsMixedRealityGestureController]や[WindowsMixedRealityController]があります。前者がHoloLens用(?)になるはずです。 | <ul><li>WindowsMixedRealityController</li><li>WindowsMixedRealityDeviceManager</li><li>WindowsMixedRealityGestureController</li><li>GenericOpenVRController</li><li>OculusRemoteController</li><li>OculusTouchController</li><li>OpenVRDeviceManager</li><li>ViveKnucklesController</li><li>ViveWandController</li><li>GenericOpenXRController</li><li>OpenXRDeviceManager</li><li>SimulatedController</li><li>SimulatedDeviceManager</li><li>SimulatedHandController</li><li>ArcadeStickController</li><li>GamepadController</li><li>JoystickController</li><li>RacingWheelController</li><li>WindowsGamingDeviceManager</li></ul> |
| Handedness  | 適用するポジションを設定します。|<ul><li>None</li><li>Left</li><li>Right</li><li>Both</li><li>Other</li><li>Any</li></ul>|
| Pointer Prefab| ポインターのオブジェクトを設定します。|ー|

###### MixedRealitySpeechCommandsProfile
音声コマンドを定義するためのプロファイルです。 音声コマンドで認識するキーワードおよび、キーコードと[MixedRealityInputActionsProfile]とのマッピングを行います。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/152548/672eb5d7-3683-1a4f-b9a1-998c31524a47.png)

| プロパティ名 | 説明 | 設定値 |
|:-:|:--|:--|
| keyword | 音声コマンドに利用するキーワードを設定します。 |　文字列 |
| KeyCode | 音声コマンドに対応するキーコードを設定します。|UnityのKeyCode|

###### MixedRealitUyControllerConfigurationProfile
入力装置であるコントローラに対する設定プロファイルです。アプリケーション内で利用する入力装置となるコントローラの定義と操作のマッピングを行います。それぞれの入力装置の具体的な動作は各SDKにゆだねられておりここでは[MixedRealityInputActionsProfile]で定義したアクションとコントローラのキーマッピングを行うことで所定の動作を実行できるようになります。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/152548/b1322729-f92e-2841-882f-85aca2409639.png)

| プロパティ名 | 説明 | 設定値 |
|:-:|:--|:--|
|Controller|コントローラの名前を設定します。|ー|
|Controller Type|コントローラのタイプを設定します。|<ul><li>WindowsMixedRealityController</li><li>WindowsMixedRealityDeviceManager</li><li>WindowsMixedRealityGestureController</li><li>GenericOpenVRController</li><li>OculusRemoteController</li><li>OculusTouchController</li><li>OpenVRDeviceManager</li><li>ViveKnucklesController</li><li>ViveWandController</li><li>GenericOpenXRController</li><li>OpenXRDeviceManager</li><li>SimulatedController</li><li>SimulatedDeviceManager</li><li>SimulatedHandController</li><li>ArcadeStickController</li><li>GamepadController</li><li>JoystickController</li><li>RacingWheelController</li><li>WindowsGamingDeviceManager</li></ul> |
|Handedness|適用するポジションを設定します。|<ul><li>None</li><li>Left</li><li>Right</li><li>Both</li><li>Other</li><li>Any</li></ul>|
|Use Custom Intraction Mapping|コントローラの操作の物理的な操作とアクションを紐づける[Intraction Mappings]のリストをカスタマイズする場合にチェックします。基本的にはチェックは不要だとおもいますが、コントローラの操作に対するアクションを増やす必要がある場合はここにチェックを行うことで[Interaction Mappings]のリスト追加を行えます。|true/false|
|Use Default Model|コントローラを表現するモデルについてデフォルトのものを使用するかどうか設定します。デフォルトのものを利用する場合はチェックを入れます。|true/false|
|Override Model|コントローラを表現するモデルを設定します。|ー|
|Interaction Mappings|コントローラの物理的な操作をアクションをマッピングします。コントローラによって使用できる操作の種類はことなるためリストはデバイスごとに変わります。ハードコピーのものはモーションコントローラ用です。|

* Interaction Mappings

| プロパティ名 | 説明 | 設定値 |
|:-:|:--|:--|
|Decscription|コントローラの物理的な操作名。例えばモーションコントローラであれば、[Thumbstick Position]で親指スティック操作を表します。
|Action|[MixedRealityInputActionsProfile]で定義したアクション名を設定します。この設定によりコントローラの操作とアクションを紐づけイベント制御を行います。|[MixedRealityInputActionsProfile]の定義値|

###### MixedRealityBoundaryVisualizationProfile

デバイスが床や移動境界面の表示を必要とする場合（WinMRなど）のそれらの色やサイズを設定するためのプロファイルです。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/152548/e1287dfe-10a7-2af5-12ee-12a29fe21966.png)

| プロパティ名 | 説明 | 設定値 |
|:-:|:--|:--|
|Play Area Settings - Material|プレイエリアのマテリアルを設定します。|MRTK_Standard_Blue|
|Tracked Area Settings - Material|トラッキングエリアのマテリアルを設定します。|MRTK_Standard_Yellow| 
|Floor Plane Settings - Material| 床面のマテリアルを設定します。|MRTK_Standard_LightGray|
|Floor Plane Settings - Scale| 床のサイズを設定します。|10,10,1|

##### Body
装着者を表すコンポーネントです。サンプルの中にはHeadオブジェクトにカメラ系のコンポーネントが設定されています。現時点ではフォーカスとゲイズに関する[Focus Provider]と[Gaze Provider]が設定されています。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/152548/de9e8278-5f2d-ee69-848f-e9feb3b36166.png)
　

### IL2CPP前提の設計（またUWP関連は考えることが増えた。。。）

これが一番大きいな変更？かもしれないですが、vNEXTはIL2CPPで作る前提になっています。このためUnityとVisual Studioでそれぞれ以下のコンポーネントが必要になります。

* Windows Store IL2CPP Scripting Backend(Unity)
* C++ ユニバーサル Windows プラットフォームツール<br />コンポーネント名：UWP用のVisual C++ ランタイム

UnityからビルドしてしまえばUWPなので大した問題ではないのですが、一度ビルドした後にUWP側でC#で書くというパターンは使えません。もっとも~.Playerプロジェクトに書けばUWPで書けるのでそれほど問題になるパターンは少ないと思います。

### 内部アーキテクチャ構造の変更
内部構造は別の記事で書きます。

## 最後に
MRTKは現行リリースされているものを単純にアップグレードするという思想ではなく、xRデバイス全ての開発での活用を目指したかなり汎用性が高いライブラリになる可能性を秘めています。正式なリリースにはまだまだ時間はかかるはずですが、これからもウォッチしていきたいと思います。