Mixed Reality Toolkit V1のあの機能はどこへ？ ~ Spatial MappingとTagalong編 ~

# Mixed Reality Toolkit V1ではこうやってできたんだけど・・・

時々ハッカソンや開発の時に「Mixed Reality Toolkit(以下MRTK) V1ではこうやってできたけど、MRTK V2ではどうやったら？」と聞かれることが色々あったります。
基本的には機能がなくなっているものはないのですが、設定や実装方法が変わっていく中で統合されたりしています。
今回はそんな中で気軽に使っていたのあの機能について紹介しておきます。

## 空間マッピングについて
HoloLensではド定番ともいえる機能の１つですね。

### 空間マッピングでの実装(V1)
Prefabを１つHierarchyに追加する形で利用できるようになっていました。

![image](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/1ced4637-f589-bc76-374b-7f9d7e0966e0.png)

こんな感じで[Holotoolkit]-[SpatialMapping]-[Prefabs]-[Spatial Mapping]のPrefabを設定します。

### 空間マッピングでの実装(V2)

MRTK V2では設定を変更するだけで実現できます。

![image](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/21c8699d-473f-1bed-6751-661437a7ad5f.png)

MixedRealityToolkitオブジェクトのInspectorタブで設定変更が可能です。  
この設定の中にある[Spatial Awareness]を選択し[Enable Spatial Awareness System]のチェックをオンにすると利用可能になります。
この中の設定にある[Spatial Observer]は各デバイスの空間マッピングの機能を通してマッピングに関する情報の管理を行います。デフォルトでは以下の２つが提供されています。[Spatial Object Mesh Observer]はUnity上のデバック実行時にテスト用のメッシュ情報を利用して空間マッピングの機能をエミュレーションすることが可能です。

* Windows Mixed Reality Spatial Mesh Observer  
HoloLens / HoloLens 2での空間マッピングに関する機能を設定  
* Spatial Object Mesh Observer  
Editorでのデバック実行時に空間マッピングの機能をエミュレートするための設定
   
## Tagalongについて

オブジェクトを視野内に常に表示するためのあの機能です。これもHoloLensではよく使っていた機能ですね。

### Tagalongの実装(V1)

MRTK V1の場合は適用したいオブジェクトに[Tagalong]コンポーネントを適用します。
Tagalong

![image](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/e81ca518-69a0-bcd9-3582-552afd29be48.png)

ちなみに、Coliderがないと視野外かを理解できないのでどんなに小さくてもColiderが必要です。


### Tagalongの実装(V2)

MRTK V2ではTagalongとしての機能は[solvers](https://github.com/microsoft/MixedRealityToolkit-Unity/blob/mrtk_release/Documentation/README_Solver.md)に吸収されています。
[Solvers](https://github.com/microsoft/MixedRealityToolkit-Unity/blob/mrtk_release/Documentation/README_Solver.md)はあるアクションを監視し、登録されたオブジェクトのコンポーネントの処理を実行します。

今回のTagalongであれば頭の位置や向きに応じて視野外になったらオブジェクトを引き戻すという処理を作ることになります。といってもMRTK V2ではすでにあるのでProfile設定とオブジェクトの構成を行うことで利用可能です。

#### solversについて
[solvers](https://github.com/microsoft/MixedRealityToolkit-Unity/blob/mrtk_release/Documentation/README_Solver.md)にはいくつかの機能があります。適用したい効果によって使い分けができます。  
それぞれに少し紹介の前に、Solverコンポーネントについての説明を。[solvers](https://github.com/microsoft/MixedRealityToolkit-Unity/blob/mrtk_release/Documentation/README_Solver.md)システムは指定したアクションの状況をトラッキングし必要なタイミングで更新処理を実行するための[Solver Handler]というコンポーネントと組合わせ利用します。  

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/8c82a2d3-a6c3-6dae-f3a3-f8440cd79632.png)

[Solver Handler]には以下の４つのパラメータを持っています。

|パラメータ|説明|
|:-:|:--|
|Tracked Target Type|トラッキングする対象の種別を設定します。現在は以下の４つを対象にトラッキングを行いSolversを呼出します。<dl><dt>Head</dt><dd>頭のポジション情報</dd><dl><dt>Motion Contoller</dt><dd>モーションコントローラ情報</dd><dl><dt>Hand Joint</dt><dd>ハンドトラッキング情報</dd><dl><dt>Custom Override</dt><dd>独自に作成したトラッキング情報</dd></dl>|
|Additional Offset|トラッキング情報に追加で与えるオフセット座標。例えば、Headトラッキングの状態で(0,0,2)とすると頭の位置＋正面方向2mの位置をSolversに渡します。|
|Additional Rotation|トラッキング情報に追加で与えるRotation。Offsetと同様基準となる情報に追加でRotation情報を与えるときに使用|
|Update Solver|後述のコンポーネントの呼出の可否を設定します。|

この[Solver Handler]は動作させるオブジェクトのコンポーネントとして追加します。このため、あまり一度に使うとパフォーマンスに影響が出るかもしれません。

そしてこの[Solver Handler]から呼び出されるSolversとして以下のものが標準で提供されています。当然カスタマイズすることで独自の部品を作成することも可能です。標準で提供されているものは以下のものです。

|種類|概要|
|:-:|:--|
|Orbital|Orbitalはトラッキング対象を中心に球体上の表面を動き回る効果が得られるSolverです。いわゆるオブジェクトが体の位置や方向に対して常に一定の位置/向きに追従するシステムです。BodyLockオブジェクトが必要な場合に利用。|
|Radial View|あるしきい値の範囲を超えた場合に、追従するSolverです。<font color="red">MRTKV1のTagalongはこの機能</font>になります。|
|InBetween|オブジェクトを2つの追跡対象オブジェクトの間に保持できるSolverです。|
|SurfaceMagnetism|MRTK V1の最後の方で追加された空間マッピング等の表面に張り付いて動くオブジェクトに適用するSolverです。|
|HandConstraint|HoloLens 2向けに用意されているSolverでMotionControllerでも利用可能です。トラッキング対象の手・コントローラの周辺に追従するオブジェクトを表示することができます。
|HandConstraintPalmUp|HoloLens 2向けに追加されたSolverです。手のひらの表裏の動きを検出しオブジェクトを制御するためのSolverになります。|

各コンポーネントはこれらの動作に合わせたパラメータを持っています。Solverの基本パラメータとして共通でもっているものは以下のものになります。
 
|パラメータ|説明|
|:-:|:--|
|Move Lerp Time|オブジェクトの移動に対して遅延時間を設定します。値が小さいほどトラッキングに対して速く動きます。|
|Rotate Lerp Time|オブジェクトの回転に対して遅延時間を設定します。値が小さいほどトラッキングに対して速く動きます。|
|Scale Lerp Time|オブジェクトのサイズ変更に対して遅延時間を設定します。値が小さいほどトラッキングに対して速く動きます。|
|Maintian Scale|チェックがある場合、オブジェクトのローカルスケールを利用します|
|Smoothing|チェックがONの場合、オブジェクトの移動/回転/サイズ変更がLerp Timeの設定に合わせて徐々に変化するようになります。
|Lifetime|Solverの有効期限を設定します。0で無制限になります。|

以降それぞれのSolverの動作をyoutubeで公開しました。どういう動きをするかの参考にしてください。

#### Orbital

いわゆるBodyLockなオブジェクトを作る場合に効果がある機能です。例えば、頭の位置に合わせてこのSolverを利用すると、頭の位置や方向に対して一定の位置にオブジェクトを配置することができます。

[![MRTK V2 - Solvers System (Orbital)](http://img.youtube.com/vi/dyd6CRcwdZw/0.jpg)](http://www.youtube.com/watch?v=dyd6CRcwdZw)

#### Radial View

MRTK V1からあるTagalongに相当する機能です。あるトラッキング対象の移動/回転によってある一定の範囲を超えた場合にオブジェクトが範囲内に移動します。

[![MRTK V2 - Solvers System (RadialView)](http://img.youtube.com/vi/cxfm9qV-feM/0.jpg)](http://www.youtube.com/watch?v=cxfm9qV-feM)

#### In Between

特定の２つのトラッキング対象の中間にオブジェクトが配置されるSolverです。Solver Handlerで定義しているトラッキング対象をメインとして、もう１つのトラッキング対象を追加し、合計２つの情報でオブジェクトの制御を行います。動画の中では[Head]と[Hand Joint]を設定し、頭と手の中間の位置にオブジェクトが追従する動作例を紹介しています。

[![MRTK V2 - Solvers System (InBetween)](http://img.youtube.com/vi/B2WKVZP8hEs/0.jpg)](http://www.youtube.com/watch?v=B2WKVZP8hEs)

#### Surface Magnetism

空間マッピング等の空間の表面に張り付く形で動くオブジェクトを作成できます。わかりやすいものではMotion Controllerのテレポートマーカーがこれと同じような動作になります。

[![MRTK V2 - Solvers System (Surface Magnetism)](http://img.youtube.com/vi/0MTxf1xF4bU/0.jpg)](http://www.youtube.com/watch?v=0MTxf1xF4bU)

#### Hand Constraint

HoloLens 2のハンドトラッキングやモーションコントローラで利用できる、コントローラ周辺にコントローラとは被らない形で追従するオブジェクトを作ることができます。

[![MRTK V2 - Solvers System (Hand Constraint)](http://img.youtube.com/vi/74o9SoeIoJg/0.jpg)](http://www.youtube.com/watch?v=74o9SoeIoJg)

#### Hand Constraint Palm Up

HoloLens 2のハンドトラッキング限定の機能になります。手の平の裏表によって発生するイベントと手に追従するオブジェクトを作ることができます。MRTK V2の例では手のひらを上にした時にメニューを表示するサンプルがあります。このサンプルの動作は[Hand Constraint Palm Up]を利用しています。

[![MRTK V2 - Solvers System (Hand Constraint Palm Up)](http://img.youtube.com/vi/2AHseNOts7M/0.jpg)](http://www.youtube.com/watch?v=2AHseNOts7M)

 
## まとめ
基本的にはMRTK V1から消えた機能はないはずです。ほとんどの機能はそのまま移行しているものが多いのです。しかし、Tagalongみたいに別の機能の１つのパターンで提供される等機能が見つからないことも時々あります。
もしMRTK V2で開発するときに、使い方がわからないというのを見かけたら追加していこうかなと思います。