Microsoft Learn  「Azure Digital Twins と Unity を使用して Mixed Reality デジタルツインを構築する」 を試してみた (前編)

# はじめに
Microsoft Build 2021 の Keynote で Metaverse ( メタバース ) の事例が紹介されたり、__MS Learn : Azure Digital Twins と Unity を使用して Mixed Reality デジタルツインを構築する__ ハンズオンセッションがあったりと、Mixed Reality と他の技術要素 ( IoT, Digital Twins etc.. ) を掛け合わせたシステム構成が今後 Mixed Reality を実装していく中でも非常に重要だと感じたので、MS Learn ラーニングパスを活用して学習をしてみたいと思います。

> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/d2f9fa83-cb72-96c6-a69d-4e560a1d1e08.png" width="500">
> [Connect IoT data to HoloLens 2 with Azure Digital Twins and Unity](https://mybuild.microsoft.com/sessions/815a692f-398b-4772-ac18-c021f5116757?source=schedule)
 > ー Microsoft Build 2021 ( 日本時間 : 5月27日 午前7時~午前8時15分 )

※基本的な手順は MS Learn に記載されているので、本記事では作業を進める中での注意点や補足情報などを共有することに重点をおいています。

# Metaverse とは!?
Microsoft Build 2021 キーノート内で Microsoft CEO のサティア・ナデラ氏が AB InBev (ベルギーに本社がある多国籍企業) の Metaverse 実装事例を紹介していましたが、詳しい内容が「Building Digital Twins, Mixed Reality and Metaverse App」で解説されていたので、こちらも少しご紹介したいと思います。 

> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/bb7d7ba4-60cb-d7a7-38dd-079ee0e79c1c.png" width="500">

> [Building Digital Twins, Mixed Reality and Metaverse Apps](https://mybuild.microsoft.com/sessions/f06287c8-8e56-452f-ae2f-e739c2be4870?source=sessions)
 > ー Microsoft Build 2021 ( 日本時間 : 5月27日 午前6時~午前6時30分 )

meta (接頭語) + verse (語幹) の造語。 直訳すると__「より包括的な宇宙」__となり、Physical World (物理世界) の上に、多層のレイヤーからなる Digital Reality (デジタルリアリティ) を重ねた世界概念を指します。この言葉が初めて使用されたのは、1992年アメリカのSF小説「Snow Crash」と言われています。Mixed Reality は 1994年に初めて定義されたので ( 現在、Microsoftが提唱している MR の定義とは少し異なる )、30年前に人々が考えていた未来が少しづつ実現可能性の高い現実になっていることが感慨深いですね。


# 本記事内で紹介するラーニングパス

- __[Azure Digital Twins と Unity を使用して Mixed Reality デジタル ツインを構築する](https://docs.microsoft.com/ja-jp/learn/paths/build-mixed-reality-azure-digital-twins-unity/)__ 
 1. Set up a mixed reality project for Azure Digital Twins in Unity
 2. Build a 3D Scene for mixed reality in unity
 3. Configure 3D assets for mixed reality in Unity
 4. Connect IoT data to HoloLens 2 with Azure Digital Twin and Unity

※ 2021/05/31 現在、こちらの学習モジュールは英語版のみとなっています。 

# 本記事の検証環境

- __Microsoft HoloLens 2__
 - __OSビルド__ :  20346.1002 (21H1)
- __Windows 10 PC__
 - __OSビルド__ : 19042.985 
 - __Windows 10 SDK__ : 10.0.19041.0
 - __Unity__ : 2020.3.8f1 (LTS) 
 - __Visual Studio 2019__ : Version 16.10.0  
   Universal Windows Platform (UWP) Workload インストール済み
 - __Microsoft Mixed Reality Feature Tool__ : v1.0.2104.3 Beta
 - Mixed Reality Toolkit v2.6.1
- __Microsoft Azure アカウント__
- __Bing Maps 開発者アカウント__
- __Azure CLI インストール済み__


※ このラーニングパスを実行する際の前提条件は、[こちら](https://docs.microsoft.com/ja-jp/learn/paths/build-mixed-reality-azure-digital-twins-unity/) をご確認ください。これ以降の手順は、ソフトウェア、ライブラリのバージョンが MS Learn 公式サイトに記載されているものと異なりますので、ご留意の上、お読みいただけますと幸いです。

# Azure Digital Twins と Unity を使用して Mixed Reality デジタル ツインを構築する

## 1. Unity で Azure Digital Twins のためのプロジェクトをセットアップする (35分)

__1.[GitHub](https://github.com/MicrosoftDocs/mslearn-mr-adt-in-unity) より ZIPフォルダ をダウンロードする__
__2.Unity Hub より Unity 2020.3.8f1 をインストールする (任意)__
__3.[Mixed Reality Feature Tool](https://docs.microsoft.com/ja-jp/windows/mixed-reality/develop/unity/welcome-to-mr-feature-tool) ( MixedRealityFeatureTool.exe ) を開く__ 

__【 補足 】 Mixed Reality Feature Tool の仕組み__
Mixed Reality Feature Tool は Mixed Reality アプリケーション開発に必要なパッケージを検索することができ、既存プロジェクトへパッケージをインポートする際に、バリデーションや圧縮ファイルのダウンロード、[manifest.json](https://docs.unity3d.com/ja/2019.4/Manual/upm-manifestPrj.html) の更新などをサポートしてくれるツールです。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/41c3eec3-1ce1-5211-ba3c-4ca79d78eab4.png" width="500">

__4.Mixed Reality Feature Tool で Project Path を指定する__

※1.で落としてきた Unity-Project フォルダを指定

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/fc1b2538-6943-b6e9-1e5e-04b279334e24.png" width="500">

__5.[Discover Features] ボタンを押す__
__6.提供された Unity プロジェクトと互換性のあるバージョンを指定する__

- Mixed Reality Toolkit Extensions 2.5.4
- Mixed Reality Toolkit Foundation 2.5.4
- Mixed Reality Toolkit GPU Stats 1.0.3
- Mixed Reality Toolkit Plane Finding 1.0.0
- Mixed Reality Toolkit Standard Assets 2.5.4
- Mixed Reality Open XR Plugin 0.1.3
- Microsoft Spatializer 1.0176
- Mixed Reality Input 0.9.2006

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/9b3e2f20-c76d-432e-7bb9-41e975d0e5d8.png" width="500">

__8.Get Features ボタンを押す__
__9.Validation ボタンを押し、エラーが無ければ Import ボタンを押す__

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/6207addb-32fa-06a7-71eb-d5ecee6754ff.png" width="500">

__10.変更点の承認が要求されるので Approve ボタンを押す__

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/eeb3655d-3144-e52c-d86a-9653b686fbdf.png" width="500">

__11.次の画面が表示されれば、インストール作業は完了です__

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/29cc9924-e15b-776f-e4a5-2674722b1ebc.png" width="500">

__( Mixed Reality Feature Tool のバージョンを更新したら.. )__
筆者の環境ではメモリを読み込むことが出来ませんでしたのエラーメッセージと共に、Mixed Reality Feature Tool が強制終了するようになってしまいました。ただ、GitHub から Clone してきたプロジェクトには既に Mixed Reality Toolkit v2.6.1 等、必要なライブラリの圧縮ファイル (xxx.tgz) が含まれており、manifest.json から PJルート/Packages/MixedReality 配下のファイルを指定する記載があるので、こちらのライブラリ等を使用して進めることにしました。

__本記事で使用したパッケージ ( 一覧 )__

- Mixed Reality Toolkit Extensions 2.6.1
- Mixed Reality Toolkit Foundation 2.6.1
- Mixed Reality Toolkit GPU Stats 1.0.3
- Mixed Reality Toolkit Plane Finding 1.0.0
- Mixed Reality Toolkit Standard Assets 2.6.1
- Mixed Reality Open XR Plugin 0.9.3
- Microsoft Spatializer 1.0.196
- Mixed Reality Input 0.9.2006
- Mixed Reality Toolkit Test Utilities 2.6.1
  

__12.Unity Hub を起動し、対象プロジェクトを追加します__

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/e1a10057-7050-0418-d9c7-4fb84535a92f.png" width="500">

## 2. Unity で Mixed Reality のための 3Dシーン をビルドする (60分)

__1.Unity プロジェクトを開く__
※ プロジェクトを開くまでに数分～10分程度かかる場合があります。

__2.Project ウィンドウより Asset > Scenes > MainScene を開く__

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/81943fa1-b269-1d16-f2c2-2bed979a3f96.png" width="500">

これからの手順はこの MainScene を編集してシーンを完成に近づけていきます。このプロジェクトは OpenXR Plug-in を使用しています。OpneXR は、開発者が幅広いAR/VRデバイスをシームレスにターゲットできるようにすることで、AR/VR開発を簡素化することを目的として、Khronos によって開発されたオープンソースプロジェクトです。この新しいプラグインを使用するためには Unity Editor の設定を少し変更する必要があります。

__3.ゲームビューへの入力ロックオプションを有効にする__
Window > Analysis > Input Debugger > Option より
__[Lock Input to Game View]__ を選択する。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/08061e97-a387-ab24-4faf-a9824aee34cd.png" width="500">

__4.Prefab フォルダを開きます__ ( Assets > Art > Prefabs )
__5.Static Terrain (地形) をドラッグ＆ドロップでシーンに追加します__

__6.追加した Static Terrain の Inspector を編集します__
Transform Position ( X = -1.25, Y = -0.59, Z = 2 )

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/02677d10-bdaa-46e8-848b-715e74530617.png" width="500">

__7.プロジェクトパネルからヒエラルキーパネルへドラッグします__
ドラッグする Prefab : Assets > Art > Prefabs > Bing Maps Design 

__8.Bing Maps Design の Inspector より Maps SDK の Developer Key を入力します__

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/1011f779-c6b9-a057-98a6-78a71477b58c.png" width="500">

__9.Bing Maps Design の Inspector より Map Renderer (Script) の値を編集します__

Bing Map 開発者用アカウントは[公式サイト](https://www.bingmapsportal.com/)より発行します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/eb24cc74-8012-1158-acce-5ce937ec9520.png" width="500">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/4ead5b8a-cacc-29b8-4c52-ad27835fb43b.png" width="500">

__10.Bing Map Design の Transform を以下値に変更します__
( X = 0, Y = -0.7, Z = 2 )

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/92cdd328-c84f-b09b-9e16-50133abffe4e.png" width="500">

__11. [Play] ボタンを押してゲームウィンドウで確認します__

Static Terrain と Dynamics Terrain の違いを観察します。Dynamic Terrain (下図 : 右) は Bing Maps より Terrain を動的に呼び出せるので、無限の地形と等高線を描画することができています。一方で、Static Terrain (下図　: 左) は Dynamic Terrain と比較し、高解像画像を使用されています。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/7499c7b6-1950-6b22-06b8-c8ed261262d7.png" width="550">

これ以降の手順では Dynamics Terrain のみを使用するので、Static Terrain は削除しておきます。

__12.Static Terrain をヒエラルキーパネルから削除します__
__13.HoloLens 2 へ作成したアプリケーションをデプロイします__

Build Settings (Ctrl+Shift+B) を開き、Universal Windows Platoform へ Switch Platform を行い、対象のシーンを指定 (Scenes/MainScene) した後、[Build]ボタンを押します。

現時点で OpenXR Plugin は、アーキテクチャ「x64 or ARM64」ビルドのみサポートしており、HoloLens 2 向けにビルドをするので __「ARM64」__ を選択します。

| Build Settings | 設定値 |
| --- | --- |
| Target Device | HoloLens |
| Architecture | ARM64 |
| Build Type | D3D Project |
| Target SDK Version | Latest installed |
| Minimum Platform Version | 10.0.18362.0 |
| Visual Studio Version | Latest installed |
| Build and Run on | USB Device |
| Build configuration | Release |

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/373433a1-6993-43a3-d96f-eaf919d6eca0.png" width="350">

__Unity 2020 + OpenXR のプロジェクト設定方法は「[Switching the build platform](https://docs.microsoft.com/en-us/windows/mixed-reality/develop/unity/tutorials/mr-learning-base-02?tabs=openxr#switching-the-build-platform)」に詳しい情報が記載されているので、こちらを参照してください。__

また、MRTK v2.6 には既知のコンパイルエラーが発見されており、HoloLens 2 + ARM64 ビルドを実行する際には、Visual Studio 2019 Version 16.8 以降を使用する必要があります。

__【 補足情報 】__
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/d08b9827-26cc-ce2c-c993-4c5f28a40661.png" width="400">

上記の既知のコンパイル問題を知らずに、Visual Studio 2019 Version 16.2 でビルドを実行すると、以下Exception ( Exception thrown at .. (GameAssembly.dll) in Azure Digital Twins.exe ... ) が発生し、アプリ起動後すぐに強制終了となったので、同様のエラーが発生した場合は、Visual Studio のバージョンも確認すると良いと思います。

__14.実機でアプリケーションの動作を確認する__

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">MS Learn - ② Build a 3D Scene for mixed reality in Unity 成果物 / Bing Map API を使用して Dynamic Terrain (動的な地形・地図) を表現することができます。<br><br>Azure Digital Twins と Unity を使用して Mixed Reality デジタルツインを構築する <a href="https://t.co/iexW9SvJC5">https://t.co/iexW9SvJC5</a> <a href="https://twitter.com/hashtag/MSBuild?src=hash&amp;ref_src=twsrc%5Etfw">#MSBuild</a> <a href="https://t.co/ZMIYYacanj">pic.twitter.com/ZMIYYacanj</a></p>&mdash; Futo Horio (@Futo_Horio) <a href="https://twitter.com/Futo_Horio/status/1399723333676060680?ref_src=twsrc%5Etfw">June 1, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

## 3. Unity で Mixed Reality のための 3Dアセットの設定を行う (40分)

Unity の Prefab システムを使用すると、すべてのコンポーネント、プロパティ値、子ゲームオブジェクトを再利用可能なアセットとして作成、構成、および保存することができます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/6d5539d1-6641-ad9a-a09c-1371fdf7fbd1.png" width="500"> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/712a277e-5378-dbc3-cad8-18f67a4af004.png" width="500">

本章でインポートする風力タービンモデルは、Autodesk Filmbox 形式 (*.fbx) であり、レンダリングパフォーマンスを向上させるためにメッシュに定義された詳細レベル ( LOD : Level Of Detail ) グループを備えています。LOD を使用することによって、Prefab と Camera との距離に基づいて、Prefab の三角ポリゴン数を切り替え、GPU処理の負荷を軽減します。

> LOD 0 (カメラとの距離が近い場合)
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/d74fdab0-5d5a-650f-b881-1205bd1d2821.png" width="250"> 
> LOD 1 (カメラとの距離が遠い場合)
> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/9413c8b4-7f74-27b6-996c-82b0034de856.png" width="250">


また、MRTK を使用することにより、シーン内に配置する風力タービン (Prefab) に没入度の高いインタラクションをすぐに実装することができます。特に、名前空間 (NameSpace) Microsoft.MixedReality.Toolkit.UI に含まれる以下のオブジェクトクラスがこのプロジェクトで使用されます。

| クラス名 | 概要 |
| --- | --- |
| __ObjectManipulator__ | オブジェクトを片手、または両手で移動、拡大・縮小、回転できるようにします |
| __BoundsControl__ | オブジェクトの周りに立方体を描画して、オブジェクトの変形が可能であること視覚的に表現すると同時に、オブジェクトの変形 ( 回転、および拡大・縮小 ) を可能にします |
| __NearInteractionGrabbable__ | Collider  |
| __RotationAxisConstraint__ | タービンがY(上)軸を中心に回転するように、オブジェクトの回転軸の制御を行います |

各デジタルツイン風力タービン Prefab には、Microsoft Azure から受信したデータを保存し、Unity プロジェクト内で対応する ScriptableObject を持っています。ScriptableObjects は基本的に、シーンやアプリケーション全体でデータをグローバルに保持できる軽量オブジェクトです。風力タービンはこの ScriptableObject を参照し続け、データが更新された際にアセットに通知を行います。以下の Prefab を見て、アタッチされている MRTK コンポーネントと、Azure データが受信される場所を確認してください。

__1.Assets > Art > Prefabs 配下の Wind Turbine Design を確認します__

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/1594d994-2b86-85a8-d014-9a51b298e984.png" width="500">

風力タービンのインスペクターを見ると、LODグループ、上記の MRTK コンポーネント、およびこのプレハブにアタッチされた他のスクリプトがあることが分かります。

__2.タービンのシミュレーションに対応した Scriptable Objects を Assets > Scriptable Objects > Trubin Site Data にて確認します__

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/4988c789-e0e9-7635-5042-ffd3263d7ab2.png" width="500">

## Static Terrain の上に風力タービンを配置する ( 任意 )

__1.Project ウィンドウ より Assets > Art > Prefabs を開きます__

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/11ce9495-6376-6e02-1af1-831b507e6622.png" width="500">

__2.これまでの手順で追加した Map ( Bing Map Design ) を削除します__
__3.ヒエラルキーウィンドウに Static Terrain.prefab をドラッグ＆ドロップします__
__4.Wind Turbine Static Map.prefab をシーンウィンドウに追加します__
__5.Wind Turbine Static Map を Static Terrain の子オブジェクトにします__

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/d956919f-91a8-4f6d-5586-f0645099258b.png" width="500">

__6.Wind Turbine Static Map のスケールを ( X=0.003, Y=0.003, Z=0.003 ) に変更し、Static Terrain のスケールと合わせます__

__7.編集メニュー項目の下にある移動ツールを選択し、Wind Turbine を Static Terrain の中央に移動させます__

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/ebeee997-7f41-ceea-0b64-dceeac29c394.png" width="500">

__8. 4.から6.の手順を繰り返し、風力タービンを追加します(任意)__

今回は MS Learn に合わせて風力タービンを3つに追加しました。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/4e24dae7-0d64-50dd-5620-85c0693f59fc.png" width="500">

__9.File > Save よりシーンを保存します__

## Dynamic Terrain の上に風力タービンを配置する

__1. [Bing Maps 開発者用アカウント](https://docs.microsoft.com/en-us/bingmaps/getting-started/bing-maps-dev-center-help/creating-a-bing-maps-account)を作成する__
__2. プロジェクトウィンドウより Assets > Art > Prefabs を開く__
__3. もし既に map がシーンに追加されている場合は削除 or 無効化する__
__4. ヒエラルキーパネルに Bing Map Design.prefab を追加する__

__5. Bing Map Design.prefab の子オブジェクトとして Wind Turbine Design を追加する__

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/d6dab2a1-4c07-a51c-4ce2-e5832cff2b71.png" width="500">

__6. 手順 5.を繰り返し、Wind Trubine Design (Prefab) を任意の位置に追加する__

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/1fe731f8-af17-3079-2536-39854bd4e571.png" width="500">

__7. File > Save でシーンを保存します__
__8. HoloLens 2 へデプロイし、端末で試します__

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">MS Learn - ③ Configure 3D Assets for Mixed Reality in Unity 成果物 / Microsoft.MixedReality.Toolkit.UI 内のオブジェクトクラスを利用して発電所の風力タービンに操作性を持たせ、Directional Indicator を使用してユーザーにタービンの位置を知らせます。<a href="https://t.co/SXKbO9vXY0">https://t.co/SXKbO9vXY0</a> <a href="https://twitter.com/hashtag/MSBuild?src=hash&amp;ref_src=twsrc%5Etfw">#MSBuild</a> <a href="https://t.co/sK08oNFzus">pic.twitter.com/sK08oNFzus</a></p>&mdash; Futo Horio (@Futo_Horio) <a href="https://twitter.com/Futo_Horio/status/1399726014276718599?ref_src=twsrc%5Etfw">June 1, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# 最後に
4つ目の学習モジュール「Azure Digital Twin と Unity を使用して IoT データを HoloLens 2 に接続する」の解説記事は後日、後編で記載予定です。最後までお読みいただき、ありがとうございました。LGTM を押していただけると嬉しいです！！！