MRTK2.7.3 + AzureSpatialAnchorsSDK2.12をHoloLens2、Android、iOSで動かす

# 環境
- Windows10 PC
- iPhone 12 Pro
- HoloLens2
- Android 10
- Unity 20203.4f1

# Azure
Azureポータルにログイン
Spatial Anchors Accountsにアクセス
各種値を入力して作成
下記値をメモしておく。
Account ID , Account Domain , Access Key

# Unity
Unity HubからProjectを作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264045/b0fce247-6776-c2e2-02d0-21017ad665cf.png)

[MixedRealityFeatureTool](https://docs.microsoft.com/ja-jp/windows/mixed-reality/develop/unity/welcome-to-mr-feature-tool)を起動しProjectPathを指定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264045/e3469c65-79a1-37c6-e794-c043168d6067.png)


Azure Spatial Anchors SDK2.12 にチェック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264045/a1cdb6d0-5c67-04ec-bef9-4bcd91dfe082.png)


MixedRealityToolkit Foundation 2.7.3にチェック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264045/2b8b2951-1562-0e96-ebac-7173fac7805a.png)

Mixed Reality OpenXR Plugin1.3.1にチェック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264045/9d36484b-8693-3f7e-a152-69f36d5e3796.png)


Get Features → Import → Approve → Exit
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264045/30be5417-f04f-e8c8-7703-4b4c1c8d69d8.png)

Unityのポップアップで[yes]を選択→再起動
MRTK Project Configurator でOpenXRを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264045/a13fac24-355b-3fd9-5f6a-e620b82d7056.png)

XR Plug-in Management Settingsに移動
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264045/6940a560-980a-5b36-d913-9a6761ac83ab.png)

ProjectSettings
PCタブでOpenXR→Microsoft HoloLens feature groupにチェック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264045/3abcc28a-6ccf-1c4e-cc10-438b58b1c2a4.png)

UWPタブでOpenXR→Microsoft HoloLens feature groupにチェック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264045/5bba9734-fd68-15d8-03e7-4ec5dc36753d.png)

iOSタブでARKitにチェック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264045/ea8c4524-e9f2-3fba-90d5-50a37a68ea84.png)

AndroidタブでARCoreにチェック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264045/a8db1d1b-a5b0-8f4a-98ab-fa6bf04a12f8.png)

OpenXRの設定に移動し下記設定
Render Mode -> Single Pass Instanced
Depth Submission Mode -> Depth 16 Bit4
Interaction Profiles → Microsoft Hand Interaction Profile
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264045/b2a96cbe-81a4-aec2-c082-82feb55087d2.png)







MRTK Project Configuratorに戻り Next → Apply
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264045/ef2991cc-a63e-e03e-a1a2-86a80df0d8d3.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264045/51494e57-ebfa-4e10-ebdd-5a9f0446913f.png)

MRTK Project Configuratorを開く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264045/d26ae84e-4333-c0b3-5eb0-7eea5ae5d413.png)
Next → Next → TMPをインポート → Done

パッケージマネージャーを開き下記PackageをImport
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264045/e85e3bad-c662-3398-4480-d64546e58c3b.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264045/b19faa98-1e02-09cd-4372-88e0557ada9a.png)
ARKit XR Plugin 4.2.2
AR Foundation 4.2.2
ARCore XR Plugin 4.2.2

File → NewScane → Basic → Create
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264045/89ab23ad-67b2-269e-ee8f-3c8e25256d6a.png)

シーンを保存
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264045/87c578a9-364f-7c62-185c-561e5dbd7359.png)

シーンにMRTKConfigureを追加
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264045/ea1fb97d-6f4b-c771-1623-52baa65549e0.png)

Create Empty → 名前をSpatialAnchorManagerに変更
AddComponent → Spatial Anchor Manager
Spatial Anchor Manager のインスペクターから下記変数にAzureの値を入力
Spatial Anchors Account Id
Spatial Anchors Account Key
Spatial Anchors Acccount Domain
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264045/fd151507-30ec-90dc-58db-ee89c86e81ee.png)


3D Object > Cube > 名前をAnchorに変更
Transform.Scale X:0.1 Y:0.1 Z:0.1
AddComponent → NearInteractioinGrabbable
AddComponent → ObjectManipulator
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264045/160d264a-ee3f-8081-6425-e3e595dd9ae1.png)

Prefab化してScaneから削除

Create Empty → 名前をTestに変更
AddComponent → NewScript → Test

```c#:Test.cs
using UnityEngine;
using Microsoft.Azure.SpatialAnchors.Unity;
using System.Threading.Tasks;
using Microsoft.Azure.SpatialAnchors;
using System;
using TMPro;

public class Test : MonoBehaviour
{
    [SerializeField] private SpatialAnchorManager spatialAnchorManager = default;
    [SerializeField] private GameObject anchorPrefab = default;
    [SerializeField] private TMP_Text text = default;
    private bool onClickedNext;
    private string anchorId;
    private GameObject anchor;

    private async void Start()
    {
        while (true)
        {
            await AnchorTest();
        }
    }

    public async Task AnchorTest()
    {
        // アンカーの作成テスト
        text.text = "Start Editor Test";
        await WaitOnClickedNext();
        text.text = "Start Session";
        await spatialAnchorManager.StartSessionAsync();
        anchor = Instantiate(anchorPrefab);
        text.text = "Place Anchor";
        await WaitOnClickedNext();
        text.text = "Save Anchor";
        var cloudNativeAnchor = anchor.AddComponent<CloudNativeAnchor>();
        await cloudNativeAnchor.NativeToCloud();
        while (!spatialAnchorManager.IsReadyForCreate)
        {
            await Task.Delay(330);
            float createProgress = spatialAnchorManager.SessionStatus.RecommendedForCreateProgress;
            createProgress = createProgress < 1 ? createProgress : 1;
            text.text = $"Spatial Scanning\nProgress rate\n{(int)(createProgress * 100)}%";
        }
        var cloudAnchor = cloudNativeAnchor.CloudAnchor;
        cloudAnchor.Expiration = DateTimeOffset.Now.AddDays(1);
        await spatialAnchorManager.CreateAnchorAsync(cloudAnchor);
        anchorId = cloudAnchor.Identifier;
        text.text = "Saved Anchor";
        await WaitOnClickedNext();
        text.text = "Stop Session";
        await WaitOnClickedNext();
        spatialAnchorManager.StopSession();
        await spatialAnchorManager.ResetSessionAsync();
        Destroy(anchor);

        // アンカーの表示テスト
        text.text = "Start Viewer Test";
        await WaitOnClickedNext();
        text.text = "Start Session";
        spatialAnchorManager.AnchorLocated += OnCloudAnchorLocated;
        void OnCloudAnchorLocated(object sender, AnchorLocatedEventArgs args)
        {
            if (args.Status != LocateAnchorStatus.Located)
                return;

            UnityDispatcher.InvokeOnAppThread(() =>
            {
                anchor = Instantiate(anchorPrefab);
                var cloudNativeAnchor = anchor.AddComponent<CloudNativeAnchor>();
                cloudNativeAnchor.CloudToNative(args.Anchor);
                text.text = "Anchor Located";
            });

        }
        var anchorLocateCriteria = new AnchorLocateCriteria();
        anchorLocateCriteria.Identifiers = new string[] { anchorId };
        await spatialAnchorManager.StartSessionAsync();
        var watcher = spatialAnchorManager.Session.CreateWatcher(anchorLocateCriteria);
        text.text = "Spacial Scanning";
        await WaitOnClickedNext();
        text.text = "Stop Session";
        await WaitOnClickedNext();
        spatialAnchorManager.AnchorLocated -= OnCloudAnchorLocated;
        spatialAnchorManager.StopSession();
        await spatialAnchorManager.ResetSessionAsync();
        Destroy(anchor);
    }

    private async Task WaitOnClickedNext()
    {
        onClickedNext = false;
        while (!onClickedNext)
        {
            await Task.Delay(100);
        }
    }

    public void OnClickedNextButton()
    {
        this.onClickedNext = true;
    }
}
```

Testのインスペクターから下記変数を登録
SpatialAnchorManager → シーンのSpatialAnchorManager
AnchorPrefab → 先ほど作成したAnchorのPrefab
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264045/f020eec1-7c3d-c261-884d-d2e6276a14eb.png)


Packages > Mixed Reality Toolkit Foundation > SDK > Features > UX >interactable > Prefabs >PressableButtonHoloLens2_48x48 ドラッグアンドドロップしてシーンに追加
Transform.Position.z → 0.5
ButtonConfigHelper > OnClick に Test > OnClickedNextButtonを登録
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264045/161aeb16-06d6-b4e3-4a50-320e21d25d27.png)



File > Save でシーンを保存
## HoloLens2
Baseを開いた状態で
File > Save as... > HoloLens2
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264045/366168e7-08ae-d5ed-2294-7faffbf71897.png)

File > Build Settings > UWP > Switch Platform
MRTK Project Configurator が出てくるのでApply > Next

シーンに戻りMixedRealityToolkitを選択 → DefaultHoloLens2ConfigurationProfileに変更
AddComponent → ARAnchorManager

MixedRealityPlayspace > MainCamera の子オブジェクトとして UI > TextMeshProを作成
下記変更を加える
Canvas
MRTK Canvas に変更
Pos X:0 Y:0.1 Z:0.8
Width:0 Height:0
Scale X:0.001 Y:0.001 Z:0.001
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264045/514f2f1c-bc85-c510-0a06-ed8b0a87e425.png)

TextMeshPro-Text
FontSize:20
Width:400
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264045/aa8481ee-7e1d-80c4-a88d-05358d5c79e5.png)

TestのインスペクターからTextに作成したオブジェクトをセット

File > Save
File > Build Settings
Add Open Scenes で Scenes/HoloLens2を追加
Build > sinファイルを開いてDebug

## Android・iOS
Baseを開いた状態で
File > Save as... > Mobile
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264045/abad3827-a727-dced-3d15-f14f124ae2bc.png)

MixedRealityToolkitを選択
Copy&Customize → Clone
Camera > Clone > Camera Settings Providers > Add Camera Settings Provider
New data provider > Type > UnityAR > UnityARCameraSettings
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264045/1c7b6745-2b64-e85c-bd04-ecd8759b5af8.png)

XR > AR Session Origin を追加
AddComponent → AR AnchorManager
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264045/396198c1-d6c5-64d9-6fc0-9c13f9f8fb6b.png)

XR > AR Session を追加
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264045/6df162a9-7096-9774-0c2f-2999df950c35.png)

UI > TextMeshPro-Textを追加
RectTransformの値を変更
Left,Top,Right,Bottom → 50
Anchors Min X:0 Y0 Max X:1 Y:1
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264045/0469367b-b38b-fc1b-0955-279b1fbfcde4.png)
TestのインスペクターからTextに作成したオブジェクトをセット

File > Save
File > Build Settings
Add Open Scenes で Scenes/Mobileを追加しScanes/HoloLens2のチェックを外す

## Android
Switch Platform > Android
MRTK Project Configurator > Apply > Next > Done
Player Settings > Playerに移動
Other Settings > Graphics APIs からVulKanを削除
Publishing Settings > Custom Main Gradle Template にチェック
Assets\Plugins\Android\mainTemplate.gradleを開きdependenciesに下記2行を追加

```
implementation('com.squareup.okhttp3:okhttp:[3.11.0]')
implementation('com.microsoft.appcenter:appcenter-analytics:[1.10.0]')
```

File > Build Settings > Build

## iOS
Switch Platform > iOS
MRTK Project Configurator > Apply > Next > Done
File > Build Settings > Build