HoloLens2をさわってみた [第4回_AzureSpatialAnchorsを使った空間同期]

はじめに

こんにちは、エンジニアの伊藤(@kazuyaplus)です。
前回はWindowsDevicePortal を使い2台目のホロレンズに、自作アプリをインストールする方法を紹介しました。

第4回ではAzureSpatialAnchorsを使い、2台のホロレンズで同じオブジェクトを同じ場所で共有する方法を紹介していきたいと思います。

第1回から同じプロジェクトを使用しているので、不明な点がある場合は第1回目から確認してみてください。

  • 第1回 : ひとりで使えるHololens2アプリをつくる ~Unity・VisualStudio・MRTKのインストールからビルドまで ~
  • 第2回 : 他の人と使えるHololens2アプリをつくる ~PUN2を使ってオブジェクトを共有~
  • 第3回 : Tips ~Wi-Fiを使ってアプリをインストール~
  • 第4回 : 他の人と同じ空間で使えるHololens2アプリをつくる ~AzureSpatialAnchorsを使った空間同期~

用語集

  • MRTK
    • [Mixed Reality Toolkit]の略で、AR、VRで使えるUIライブラリ
  • PUN2
    • [Photon Unity Networking2]の略で、Unityにオンライン機能を組み込むためのサービス
  • AzureSpatialAnchors
    • 複数のユーザーが同じ物理的な場所にデジタルコンテンツを配置できるようにするためのサービス

検証環境

  • Unity:2020.3.26f1
  • MRTK:2.7.3
  • VisualStudio:2019
  • Device:HoloLens2

手順

シーンの準備

[Hierarchy]で、SharedPlaygroundオブジェクトを展開し、さらにTableAnchorオブジェクトを展開します。

プロジェクトウィンドウで、Assets > MRTK.Tutorials.MultiUserCapabilities > Prefabsフォルダーに移動し、

ButtonsプレハブをTableAnchorにドラッグして、TableAnchorオブジェクトの子としてシーンに追加します。

シーンを操作するためのボタンの構成

次に、AzureSpatialAnchorsを使用するために、ボタンイベントを設定していきます。

[Hierarchy]で、Buttonオブジェクトを展開し、[StartAzureSession]を選択します。

[Inspector]で、Interactableコンポーネントを見つけ、OnClickイベントを次のように設定します。

  • None(Object)フィールドに、TableAnchorオブジェクトを割り当てます。
  • [NoFunction]から、 AnchorModuleScript > StartAzureSessionを選択します。

次に同じ階層内の、[CreateAzureAnchor]を選択します。

同じように、Interactableコンポーネントを見つけ、OnClickイベントを次のように設定します。

  • None(Object)フィールドに、TableAnchorオブジェクトを割り当てます。
  • [NoFunction]から、 AnchorModuleScript > CreateAzureAnchorを選択します。
  • 表示される新しいNone(Object)フィールドに、TableAnchorオブジェクトを割り当てます

次に同じ階層内の、[ShareAzureAnchor]を選択します。

同じように、Interactableコンポーネントを見つけ、OnClickイベントを次のように設定します。

  • None(Object)フィールドに、TableAnchorオブジェクトを割り当てます。
  • [NoFunction]から、 SharingModuleScript > ShareAzureAnchorを選択します。

次に同じ階層内の、[GetAzureAnchor]を選択します。

同じように、Interactableコンポーネントを見つけ、OnClickイベントを次のように設定します。

  • None(Object)フィールドに、TableAnchorオブジェクトを割り当てます。
  • [NoFunction]から、 SharingModuleScript > GetAzureAnchorを選択します。

Azureアカウントを作成する

AzureSpatialAnchorsを使うために、Azureのアカウントをこちらから作成しましょう。

アカウントを作成したら、画像の赤枠で囲った箇所の[Account ID] [Account Domain] [Primary key]をコピーしておきましょう。

シーンをAzureリソースに接続する

[Hierarchy]で、SharedPlaygroundオブジェクトを展開し、TableAnchorオブジェクトを選択します。

[Inspector]で、Spatial Anchor Manager(スクリプト)コンポーネントを見つけます。

事前に作成したAzureSpatialAnchorsアカウントの情報を使用して[Credentials]セクションを設定します。 

  • [Spatial Anchors Account ID]フィールドに、Azure SpatialAnchorsアカウントの[Account ID]を貼り付けます。
  • [Spatial Anchors Account Domain]フィールドに、Azure SpatialAnchorsアカウントの[Account Domain]を貼り付けます。
  • [Spatial Anchors Account Key]フィールドに、 Azure SpatialAnchorsアカウントから[Primary key]を貼り付けます。

[Hierarchy]でTableAnchorオブジェクトを選択し、[Inspector]で[Anchor Module Script]コンポーネントを見つけます。

[Public Sharing Pin]フィールドで、ピンがプロジェクトに固有になるように数桁を変更します。

TableAnchorオブジェクトを選択したまま、[Inspector]で、すべてのスクリプトコンポーネントが有効になっていることを確認します。

一部スクリプトを追加

既に修正されている可能性があるので要確認ですが、この後、紹介する最後の同期手順の7番でGet Azure Anchorボタンを押すと、

DebugWindow で "Local anchor position successfully set to Azure anchor position" と表示され、

デバイス1と同じ位置にオブジェクトが移動するようになっているはずですが、AnchorModuleScript.cs の、

下記の箇所がなぜか抜けているために、正常に動作しなかったので、私の場合は下記部分を追加しました。

AnchorModuleScript.cs

#if WINDOWS_UWP || UNITY_WSA
                // HoloLens: The position will be set based on the unityARUserAnchor that was located.

                // Create a local anchor at the location of the object in question
                gameObject.CreateNativeAnchor();

                // Notify AnchorFeedbackScript
                OnCreateLocalAnchor?.Invoke();

                // On HoloLens, if we do not have a cloudAnchor already, we will have already positioned the
                // object based on the passed in worldPos/worldRot and attached a new world anchor,
                // so we are ready to commit the anchor to the cloud if requested.
                // If we do have a cloudAnchor, we will use it's pointer to setup the world anchor,
                // which will position the object automatically.
                if (currentCloudAnchor != null)  
                {
                    Debug.Log("Local anchor position successfully set to Azure anchor position");

                    //gameObject.GetComponent<UnityEngine.XR.WSA.WorldAnchor>().SetNativeSpatialAnchorPtr(currentCloudAnchor.LocalAnchor);

                    Pose anchorPose = Pose.identity;
                    anchorPose = currentCloudAnchor.GetPose();

                    Debug.Log($"Setting object to anchor pose with position '{anchorPose.position}' and rotation '{anchorPose.rotation}'");
                    transform.position = anchorPose.position;
                    transform.rotation = anchorPose.rotation;

                    //removeAnchor = "Inactive";
                    //Create a native anchor at the location of the object in question
                    gameObject.CreateNativeAnchor();

                    //Notify AnchorFeedbackScript
                    OnCreateLocalAnchor?.Invoke();

                }

WindowsDevicePortal でメッシュをつくる

空間にアンカーを設定する必要があるので、WindowsDevicePortal を開いて設定していきましょう。

WindowsDevicePortalの開き方については、第3回を確認してください。

WindowsDevicePortalを開き、左のメニューから Views > 3D View を開くと下のような画面になっていると思います。

あたりを少し見まわした後、Spatial mapping > Update を押してみましょう、メッシュが生成されると思います。

メッシュが生成されたら、Spatial anchors > Update を押してみましょう、ロケーターが生成されると思います。

同期手順

ここまで出来たら、準備ができましたので、同期してみましょう。

2つのデバイス間でAzure Anchor IDを共有し空間を同じ配置するためには、次の手順のように進めます。

※AzureSpatialAnchorsはUnityでは実行できません。そのため、AzureSpatialAnchorsの機能をテストするには、2つのデバイスにプロジェクトをビルドする必要があります。

  1. デバイス1(ホスト)の場合:アプリを起動します(インスタンス化されたオブジェクトがテーブルに配置されます)
  2. デバイス2(ゲスト)の場合:アプリを起動します(オブジェクトとアバターが表示されますがホストと同じ場所に表示されません)
  3. デバイス1の場合: [Start Azure Session] ボタンを押します。
  4. デバイス1の場合: [Create Azure Anchor ] ボタンを押します。
  5. デバイス1の場合: [Share Azure Anchor] ボタンを押します。
  6. デバイス2の場合: [Start Azure Session] ボタンを押します。
  7. デバイス2の場合: [Get Azure Anchor] ボタンを押します(デバイス1でアンカーが作成された場所にオブジェクトが移動します)

おわりに

これで、2台のHololens2を使い、同じ空間でオブジェクトを共有することができるようになりました。

4週に渡り、Hololens2の基本的なアプリ作成について紹介しました。

基本的にMicrosoftが用意してある、チュートリアル通りではありますが、私自身がつまずいたりした点に関して補足してあります。

このブログが少しでもHololens2ユーザーの助けになればうれしいです。全4回、お疲れさまでした!

参考リンク

docs.microsoft.com

docs.microsoft.com

github.com

HoloLens2をさわってみた [第3回_Wi-Fiを使ってアプリをインストール]

f:id:kazuyaplus:20220214152337p:plain

はじめに

こんにちは、エンジニアの伊藤(@kazuyaplus)です。
前回はPUN2を使い、キューブなどをUnityとホロレンズで同期できるようにしました。

第3回ではWindowsDevicePortalを使い、自作のアプリをもう1台のホロレンズにインストールする方法を紹介していきたいと思います。

  • 第1回 : ひとりで使えるHololens2アプリをつくる ~Unity・VisualStudio・MRTKのインストールからビルドまで ~
  • 第2回 : 他の人と使えるHololens2アプリをつくる ~PUN2を使ってオブジェクトを共有~
  • 第3回 : Tips ~Wi-Fiを使ってアプリをインストール~
  • 第4回 : 他の人と同じ空間で使えるHololens2アプリをつくる ~AzureSpatialAnchorsを使った空間同期~

用語集

  • MRTK
    • [Mixed Reality Toolkit]の略で、AR、VRで使えるUIライブラリ
  • PUN2
    • [Photon Unity Networking2]の略で、Unityにオンライン機能を組み込むためのサービス
  • AzureSpatialAnchors
    • 複数のユーザーが同じ物理的な場所にデジタルコンテンツを配置できるようにするためのサービス

検証環境

  • Unity:2020.3.26f1
  • MRTK:2.7.3
  • VisualStudio:2019
  • Device:HoloLens2

手順

パッケージの作成

第2回のプロジェクトの続きから始めるので、不明な点がある場合は第2回目を確認してみてください。

ではさっそく、第2回でつくったプロジェクトをビルドしましょう、ビルド設定を下の画像のようにします。

f:id:kazuyaplus:20220205143610j:plain

Unityからビルドしたら、画像のような構成になっていると思います。

[MRTK Tutorials.sin]をVisual Studioで開きましょう。

f:id:kazuyaplus:20220219210939p:plain

プロジェクト > 公開 > アプリパッケージの作成を選択してください。

f:id:kazuyaplus:20220219211725p:plain

次に配布方法を選択します、サイドローディングの方にチェックをつけます。

f:id:kazuyaplus:20220219212202p:plain

次は署名方法の選択ですが、私の場合は証明書が必要だったので、使用するの方にチェックをいれます。

f:id:kazuyaplus:20220219212708p:plain

パッケージの選択と構成は今回はホロレンズでのみ使用する予定なので、ARM64だけにチェックをつけています。

f:id:kazuyaplus:20220219212735p:plain

f:id:kazuyaplus:20220219212800p:plain

パッケージが完了したら、出力先を開きましょう、ここで必要なのは下記の3つになります。

  • [MRTK Tutorials_1.0.0.0_ARM64.cer]

  • [MRTK Tutorials_1.0.0.0_ARM64.appx]

  • Dependencis > ARM64 > [Microsoft.VCLibs.ARM64.14.00.appx]

f:id:kazuyaplus:20220219214022p:plain

f:id:kazuyaplus:20220219214024p:plain

WindowsDevicePortal を使ってインストール

ホロレンズの電源を入れ、WindowsDevicePortalを開きましょう。

ホロレンズの設定 > ネットワークとインターネット > Wi-Fi > アダプターのプロパティから

IPアドレスを確認し、ブラウザにIPアドレス( https://〇〇〇 )を入力します。

f:id:kazuyaplus:20220219220027p:plain

WindowsDevicePortalを開いたら左のメニューから[Apps]を選択

Deploy apps > Install Certificate > [MRTK Tutorials_1.0.0.0_ARM64.cer]をいれましょう。

f:id:kazuyaplus:20220219215413p:plain

次にLocal Storageを開いて[MRTK Tutorials_1.0.0.0_ARM64.appx]を選択し、NEXTで次に進みます。

f:id:kazuyaplus:20220219215552p:plain

Dependencis > ARM64 > [Microsoft.VCLibs.ARM64.14.00.appx]を選択したらインストールしましょう。

f:id:kazuyaplus:20220219215644p:plain

おわりに

これで、2台のホロレンズに同じアプリをインストールができ、ホロレンズ間でオブジェクトを共有することができるようになりました。

次はAzureSpatialAnchorsを使って、空間を共有する方法を紹介します。

参考リンク

docs.microsoft.com

HoloLens2をさわってみた [第2回_他の人と使えるHololens2アプリをつくる]

f:id:kazuyaplus:20220214152337p:plain

はじめに

こんにちは、エンジニアの伊藤(@kazuyaplus)です。
前回はMRTKを使い、キューブを動かしたり回したりできるようにしました。

第2回ではPUN2を使い、UnityエディタとHololens2でキューブの動きを共有する方法を紹介していきたいと思います。

  • 第1回 : ひとりで使えるHololens2アプリをつくる ~Unity・VisualStudio・MRTKのインストールからビルドまで ~
  • 第2回 : 他の人と使えるHololens2アプリをつくる ~PUN2を使ってオブジェクトを共有~
  • 第3回 : Tips ~Wi-Fiを使ってアプリをインストール~
  • 第4回 : 他の人と同じ空間で使えるHololens2アプリをつくる ~AzureSpatialAnchorsを使った空間同期~

用語集

  • MRTK
    • [Mixed Reality Toolkit]の略で、AR、VRで使えるUIライブラリ
  • PUN2
    • [Photon Unity Networking2]の略で、Unityにオンライン機能を組み込むためのサービス
  • AzureSpatialAnchors
    • 複数のユーザーが同じ物理的な場所にデジタルコンテンツを配置できるようにするためのサービス

検証環境

  • Unity:2020.3.26f1
  • MRTK:2.7.3
  • VisualStudio:2019
  • Device:HoloLens2

手順

追加機能を有効にする

第1回のプロジェクトの続きから始めるので、不明な点がある場合は第1回目を確認してみてください。

さっそく始めていきましょう、Unityメニューで、Edit > Project Settings を選択して[Player]ウィンドウを開き、

Universal Windows Platform Settingsタブから [Publishing Settings]を見つけます。

[Capabilities]の設定で[InternetClient] [Microphone] [SpatialPerception] [GazeInput]が有効になっていることを確認します。

さらに追加で以下の機能を有効にします。

  • InternetClientServer機能
  • PrivateNetworkClientServer機能

f:id:kazuyaplus:20220215203329j:plain

空間認識システムを有効にする

[Hierarchy]でMixedRealityToolkitオブジェクトを選択して、[Inspector]を開きます。

[DefaultHololens2 Configuration Profile]をクローンして新しいプロファイルを作成します。

f:id:kazuyaplus:20220215203442j:plain

次に、[Spatial Awareness]セクション で [Enable Spatial Awareness System] を有効にします。

有効にしたら[DefaultMixedRealitySpatialAwarenessSystemProfile] をクローンします。

f:id:kazuyaplus:20220215203612j:plain

クローンができたら[XR SDK WindowsMixedRealitySpatialMesh Observer] を展開します。

展開したら、[DefaultMixedRealitySpatialAwarenessMeshObserverProfile] をクローンします。

f:id:kazuyaplus:20220219141902j:plain

クローンができたら DisplaySettings > DisplayOption をOcclusionにします。

f:id:kazuyaplus:20220215203829j:plain

オリジナルの空間データを使用するには

引き続き[Spatial Awareness]セクションで新たに [SpatialObjectMeshObserver] タイプのオブザーバーを追加します。

[DefaultObjectMeshObserverProfile] をクローンします。

f:id:kazuyaplus:20220401172617p:plain

チュートリアルアセットのインポート

次のUnityパッケージをこのリンクからダウンロードして、下記の順番にUnityにインポートしていきます。

  1. MRTK.HoloLens2.Unity.Tutorials.Assets.GettingStarted.2.7.2.unitypackage
  2. MRTK.HoloLens2.Unity.Tutorials.Assets.AzureSpatialAnchors.2.7.2.unitypackage
  3. MRTK.HoloLens2.Unity.Tutorials.Assets.MultiUserCapabilities.2.7.2.unitypackage

※MultiUserCapabilitiesアセットパッケージをインポートした後、コンソールウィンドウに、タイプまたは名前空間がないという大量のCS0246エラーが表示されます。これは、PUNアセットをインポートしたら解決されるので、次に進んでください。

PUNアプリケーションの作成

Photonアカウントの作成につきましては省略します。作成手順につきましては参考サイトを確認してください。

準備ができたら、下記のような画面になっていると思いますので[App ID] をコピーしておきます。

f:id:kazuyaplus:20220218171307j:plain

Unityに戻り、メニューの Window > Asset Store を選択して開き、[PUN2-FREE]を検索して選択し、アセットをインポートします。

インポートしたら、Window > Photon Unity Networking > PUN Wizardを選択してPunWizardウィンドウを開き、 [Setup Project]ボタンをクリックして[PUN Setup]メニューを開きます。

[App ID]フィールドに、前の手順でコピーしたPUNの[App ID]を貼り付けます。

次に、[Setup Project]ボタンをクリックして、アプリIDを適用します。

f:id:kazuyaplus:20220215204557j:plain

PUN Setupに[App ID]をいれると Assets > Photon > PhotonUnityNetworking > Resources に[PhotonServerSettings]ができます。

f:id:kazuyaplus:20220218171538j:plain

これで、PUNアプリと、Unityのプロジェクトを同期する準備ができました。

同期するシーンの準備

プロジェクトウィンドウで、 Assets > MRTK.Tutorials.MultiUserCapabilities > Prefabsフォルダーに移動し、次のプレハブをクリックして[Hierarchy]にドラッグし、シーンに追加します。

  • NetworkLobby
  • SharedPlayground

f:id:kazuyaplus:20220215205455j:plain

プロジェクトウィンドウで、 Assets > MRTK.Tutorials.AzureSpatialAnchors > Prefabsフォルダーに移動し、[ DebugWindow ]をクリックして[Hierarchy]にドラッグし、シーンに追加します。

f:id:kazuyaplus:20220215205623j:plain

プロジェクトウィンドウで、 Assets >  MRTK.Tutorials.MultiUserCapabilities > Resourcesフォルダーに移動します。

[Hierarchy]で、NetworkLobbyオブジェクトを展開し、 NetworkRoomを選択します。次に、Inspectorで、[Photon Room]コンポーネントを見つけて、次のように構成します。

[Photon User Prefab]フィールドに、ResourcesフォルダーからPhotonUserプレハブを割り当てます。

f:id:kazuyaplus:20220215205934j:plain

[Hierarchy] で、MixedRealityPlayspaceオブジェクトを展開し、[MainCamera] オブジェクトを選択します。

次に、[Inspector]から [AR Camera Manager]を追加します。

f:id:kazuyaplus:20220219144656p:plain

続いて、 Assets > MRTK.Tutorials.MultiUserCapabilities > Prefabsフォルダーに移動し、TableAnchorプレハブを[Hierarchy] のSharedPlaygroundオブジェクトにドラッグして、SharedPlaygroundの子としてシーンに追加します。

f:id:kazuyaplus:20220219145045p:plain

TableAnchorオブジェクトを選択し、[MainCamera] コンポーネントをTableAnchorの[AR Session Origin] のカメラフィールドにドラッグします。

f:id:kazuyaplus:20220219145234p:plain

キューブなどを同期する

ここまでは、だいたい参考サイトのチュートリアル通りになりますが、自分で用意したオブジェクトも同期させてみたいので、第1回目で作成したキューブの同期もできるように、色々追加していきたいと思います。

  1. [ cube ] をプレハブにして開きます。
  2. [ PhotonView ]スクリプトをつけます、そのまま展開して[Ownership] > [Ownership Transfer] > [Takeover]にします。
  3. [ Generic Net Sync ] スクリプトをつけます。
  4. [ OwnershipHandler ] スクリプトをつけます。
  5. [ Table Anchor As Parent ] スクリプトをつけます。

f:id:kazuyaplus:20220219161326p:plain

キューブを同期するために、[PhotonRoom.cs] に少しコードを追加しましょう。

PhotonRoom.cs

        public static PhotonRoom Room;

        [SerializeField] private GameObject photonUserPrefab = default;
        [SerializeField] private GameObject roverExplorerPrefab = default;
        [SerializeField] private GameObject TestExplorerPrefab = default;  //←追加
        [SerializeField] private Transform roverExplorerLocation = default;

PhotonRoom.cs

        private void Start()
        {
            if (PhotonNetwork.PrefabPool is DefaultPool pool)
            {
                if (photonUserPrefab != null) pool.ResourceCache.Add(photonUserPrefab.name, photonUserPrefab);

                if (roverExplorerPrefab != null) pool.ResourceCache.Add(roverExplorerPrefab.name, roverExplorerPrefab);

                if (TestExplorerPrefab != null) pool.ResourceCache.Add(TestExplorerPrefab.name, TestExplorerPrefab); //←追加
            }
        }

PhotonRoom.cs

        private void CreateInteractableObjects()
        {
            var position = roverExplorerLocation.position;
            var positionOnTopOfSurface = new Vector3(position.x, position.y + roverExplorerLocation.localScale.y / 2,
                position.z);

            var go = PhotonNetwork.Instantiate(roverExplorerPrefab.name, positionOnTopOfSurface,
                roverExplorerLocation.rotation);

            var goTest = PhotonNetwork.Instantiate(TestExplorerPrefab.name, positionOnTopOfSurface,
                roverExplorerLocation.rotation); //←追加

コードの追加ができたら、PhotonRoom.cs のフィールドにオブジェクトを追加していきましょう。

  1. プロジェクトウィンドウで、 Assets > MRTK.Tutorials.MultiUserCapabilities > Resourcesフォルダーに移動します。
  2. [Hierarchy]で、NetworkLobbyオブジェクトを展開し、 NetworkRoomオブジェクトを選択します。
  3. 次に、[Inspector]で、[Photon Room]コンポーネントを見つけて、Rover Explorer Prefabフィールドに、Resourcesフォルダーから[RoverExplorer_Complete_Variant]プレハブを割り当てます。
  4. 同様に、[Inspector]で、[Photon Room]のTest Explorer Prefabフィールドに、Resourcesフォルダーから[cube]プレハブを割り当てます。
  5. [Photon Room]コンポーネントのRover Explorer Locationフィールドに、 HierarchyウィンドウからTableAnchorの子の[Table]オブジェクトを割り当てます。

f:id:kazuyaplus:20220219172256p:plain

できたらホロレンズにビルドして確認してみましょう、Photonで同期したことにより、Unityやホロレンズで動かしたものが互いに共有されていることが確認できると思います。

f:id:kazuyaplus:20220219173744p:plain

おわりに

ここまで出来たら2台目のホロレンズにビルドを入れて遊んでみたい人が多いのではないのでしょうか?

ということで、次は、Wi-Fi経由でビルドをインストールする方法を紹介します。

参考リンク

docs.microsoft.com

yotiky.hatenablog.com

HoloLens2をさわってみた [第1回_ひとりで使えるHololens2アプリをつくる]

f:id:kazuyaplus:20220214152337p:plain

はじめに

こんにちは、エンジニアの伊藤(@kazuyaplus)です。
Hololens2すごい!Hololens2を使って一緒にいる人たちと同じARを共有して、物を動かしたりしたい!

そう思ってHololens2で基本的なアプリをビルドしてみました。

この記事ではHololens2で基本的なアプリを作る方法を全4回にわけてまとめていきたいと思います。

  • 第1回 : ひとりで使えるHololens2アプリをつくる ~Unity・VisualStudio・MRTKのインストールからビルドまで ~
  • 第2回 : 他の人と使えるHololens2アプリをつくる ~PUN2を使ってオブジェクトを共有~
  • 第3回 : Tips ~Wi-Fiを使ってアプリをインストール~
  • 第4回 : 他の人と同じ空間で使えるHololens2アプリをつくる ~AzureSpatialAnchorsを使った空間同期~

細かいことは後でいいので、Hololens2でとにかく何かを動かしたい人に向けて紹介していきます。

詳しいことは下のほうにすばらしい参考リンクをまとめていますので、そちらも確認してみてください。

用語集

  • MRTK
    • [Mixed Reality Toolkit]の略で、AR、VRで使えるUIライブラリ
  • PUN2
    • [Photon Unity Networking2]の略で、Unityにオンライン機能を組み込むためのサービス
  • AzureSpatialAnchors
    • 複数のユーザーが同じ物理的な場所にデジタルコンテンツを配置できるようにするためのサービス

検証環境

  • Unity:2020.3.26f1
  • MRTK:2.7.3
  • VisualStudio:2019
  • Device:HoloLens2

手順

Unityのインストール

インストールするモジュールを選択します。

  • Microsoft Visual Studio Community 2019
  • Universal Windows Platform Build Support

f:id:kazuyaplus:20220209183313j:plain

VisualStudioの追加インストール

Visual Studio Installerを起動し[変更]をクリックします。

f:id:kazuyaplus:20220209183537j:plain

[ユニバーサル Windows プラットフォーム開発]と下記の項目にチェックします。

  • USBデバイスの接続
  • C++(v142)ユニバーサルWindowsプラットフォーム
  • Windows 10 SDK (10.0.19041.0) 既に含まれている場合はそのまま

f:id:kazuyaplus:20220209183713j:plain

追加インストールが終わったら、Unityを起動しましょう。

f:id:kazuyaplus:20220209183844j:plain

スクリプトエディターの確認

  1. メニューの Edit > Preferences > Unity Preferences を開きます。
  2. [External Tools] の [External Script Editor] を [Visual Studio 2019] に設定します。

f:id:kazuyaplus:20220209184117j:plain

ビルド プラットフォームを切り替える

  1. Unity のメニューで、[File] > [Build Settings...] の順に設定して、[Build Settings] を開きます。
  2. [Build Settings] で、[Universal Windows Platform] を選択し、次の設定を完了します。

  3. [Target Device] を [HoloLens] に設定します。

  4. [Architecture] を [ARM 64] に設定します。
  5. [Build Type] を [D3D Project] に設定します。
  6. [Target SDK Version] を [Latest installed] に設定します。
  7. [Minimum Platform Version] を 10.0.10240.0 に設定します。
  8. [Visual Studio Version] を [Latest installed] に設定します。
  9. [Build and Run on] を [USB Device] に設定します。
  10. [Build configuration] を [Release] に設定します。

  11. [Switch Platform] を選択します。

f:id:kazuyaplus:20220209184846j:plain

MRTKのインポート

最新バージョンの Mixed Reality Feature Tool を Microsoft ダウンロード センターからダウンロードします。

www.microsoft.com

ダウンロードしたものを展開すると下記のようになっていると思うので、[MixedRealityFeatureTool.exe]を起動します。

f:id:kazuyaplus:20220209185626j:plain

[Start]を押して次へ

f:id:kazuyaplus:20220209185058j:plain

開いたらプロジェクトフォルダーを選択します。

f:id:kazuyaplus:20220213164027j:plain

Mixed Reality Toolkit に関連するパッケージを選択していきます。

  1. [Mixed Reality Toolkit Foundation] がオンになっていることを確認し、そのフィールドに [MRTK 2.7.3] を選択します。
  2. [Mixed Reality OpenXR Plugin] がオンになっていることを確認し、利用可能な最新バージョンを選択します。

※ Azure Spatial Anchorsを使う予定の場合は追加で [Azure Spatial Anchors SDK Core]と[Azure Spatial Anchors SDK for Windows(プラットフォーム固有のパッケージ)]を追加します。

f:id:kazuyaplus:20220213164129j:plain

Unityプロジェクトを構成する

Mixed Reality Feature Tool で機能の追加が終了したらUnityを起動します。

パッケージがインポートされたら、Unity エディターを再起動し、新しいプラグインのバックエンドを有効にします。 起動時に警告が出ますが[はい] を選択します。

f:id:kazuyaplus:20220213164454j:plain

起動時にMRTKが立ち上がります。

[Unity OpenXR Plugin] を押して次のページに進みます。

f:id:kazuyaplus:20220213164536j:plain

[Show XR Plug-in Management Settings] を押すとプロジェクト設定が立ち上がります。

f:id:kazuyaplus:20220213164613j:plain

[XR Plug-in Management] でユニバーサル Windows プラットフォーム設定 がアクティブになっていることを確認し、[Initialize XR on Startup]、[Open XR]、[Microsoft HoloLens feature set] がすべて有効になっていることを確認します。(チェックボックスがオンになっている)

※警告マークはクリックして [FixAll]

f:id:kazuyaplus:20220213164635j:plain

OpenXR 構成を検証するには、[XR Plug-in Management] で [OpenXR] を選択し、次の項目がオンになっていることを確認します。

  • Depth Submission Mode : Depth 16 Bit
  • Interaction Profiles : Microsoft Hand Interaction Profile

f:id:kazuyaplus:20220213164804j:plain

設定を有効にするには、Unity を再起動する必要があります。 メッセージが表示されたら、[Apply] を選択して Unity エディターを再起動します。

f:id:kazuyaplus:20220213164827j:plain

  1. 再起動が終わったら、Unity のメニューで、[Edit] > [Project Settings...] を選択して [Project Settings] ウィンドウを開きます。
  2. [Project Settings] で、[Player] > [Publishing Settings] の順に選択し、[Package name] フィールドに適切な名前を入力します、適当な名前を付けたら、保存しましょう。

f:id:kazuyaplus:20220213164903j:plain

シーンを作成してMRTKを作成する

Unity メニューで、 Mixed Reality > Toolkit > Add to Scene and Configure を選択して、MRTK を現在のシーンに追加します。

f:id:kazuyaplus:20220213165025j:plain

[Hierarchy] ウィンドウで MixedRealityToolkit オブジェクトを選択した状態で、[Inspector] ウィンドウで [MixedRealityToolkit] 構成プロファイルが DefaultMixedRealityToolkitConfigurationProfile に設定されていることを確認します。

f:id:kazuyaplus:20220213165059j:plain

f:id:kazuyaplus:20220213165112j:plain

次にヒエラルキーにキューブを作ります。

  • 位置: X = 0、Y = -0.1、Z = 0.5
  • 回転:X = 0、Y = 0、Z = 0
  • スケール: X = 0.1、Y = 0.1、Z = 0.1

追跡対象の手でオブジェクトを操作してつかむには、オブジェクトに次のコンポーネントが必要です。

  • Object Manipulator (Script) コンポーネント (ConstraintManagerは自動でセットされる)
  • NearInteractionGrabbable (Script) コンポーネント

f:id:kazuyaplus:20220213165235j:plain

プロジェクトをビルドする

Unity メニューで、 [File] > [Build Settings...] を選択し、[Build Settings] からプロジェクトをビルドします。 ビルドが完了したら下記のフォルダのようになります。

f:id:kazuyaplus:20220213165517j:plain

[MRTK Tutorials.sin] をVisual Studioで開きます。

ビルド設定を [Release] 、[ARM64] 、[デバイス] にします。

f:id:kazuyaplus:20220213165544j:plain

設定が終わったらホロレンズ本体とパソコンを接続しましょう。 初回のみVisual StudioとHoloLens 2のペアリングを求められます。

HoloLens2本体の設定内の[更新とセキュリティ] > [開発者向け]にある[ペアリング]ボタンを押すとPINが表示されます。

f:id:kazuyaplus:20220213165621j:plain

ビルドが終わったら、ホロレンズでアプリを起動します。 下記の画像はUnityで実行した画面になりますが、アプリを実行するとキューブを掴むことができるようになっているかと思います。

f:id:kazuyaplus:20220213212427j:plain

おわりに

これでキューブを動かしたり回したりすることができるようになりました。

次回は、このアプリケーションを他の人と一緒に使えるようにする方法を紹介します。

参考リンク

【イベントレポート】SIer・業務系エンジニアのXRスタートアップ転職を語る会

こんにちは、エンジニアのクロックスこと黒岩(@kro96_xr)です。
今回は先日行われたSIer・業務系エンジニアのXRスタートアップ転職を語る会のイベントレポートをお届けします。

▼アーカイブはこちら▼
www.youtube.com

イベント概要

本イベントはSynamon社内のSIer出身者が各自のXR転職を振り返りつつパネルディスカッションを行うという形式で行われました。

「業務でXR開発はやったことないけど、XR業界に転職したい」
「SIerの経験って何がどう活かせるの?」
「XR開発やりたいけど、Unity業務経験必須なら無理かな…」
「何はともあれ、XR転職を成功させた人のお話が聞きたい!」

XR転職を目指しながらも、実態がわからない&何をアピールすればいいのかわからないといった方々、中々多いのではないでしょうか。
今回はSynamon内の元SIerメンバーが自身のXR転職を振り返りつつ、皆さんのお悩みに答えていきたいと思います!
(イベントページより引用)

なお、当日は以下の流れで進行しました。
f:id:krocks96:20220206170043p:plain

自己紹介~「VRは体力ですよ」~

自己紹介の見どころはうぃすきーさんが三点倒立し始めたところですね。

うぃすきーさん曰く「VRは体力ですよ」とのことですので、みなさん体力付けていきましょう!

テーマ①「自分、こうやってXR転職しました」

このテーマでは各自がSynamonに入社するまでの経緯をお話ししました。
f:id:krocks96:20220206203456p:plain

クロックス

  • SIerで製造業向けパッケージソフトの運用保守・開発をやっていた
  • 2018年夏の6社合同採用イベントでSynamonを知る
  • 開発スキル不足を自覚していたので未経験待遇でWebエンジニアへ(年収は3桁万減)
  • 2021年にあらためて応募、1回お祈りされてからのスカウトにより入社

うぃすきーさん

  • SIerでインフラ担当をしていた
  • 開発経験を積むためにWeb系の会社に転職(年収は半減)
  • 自力で一から開発する経験を積んでSynamonに入社

じゅーいちさん。

  • Synamonはいつの間にか知っていた
  • おそらくTwitterで界隈の動きを追っているときに知った
  • リアルイベントが多かった時期で、参加している中で開発されている方や会社を知った…と思う
  • 1年間くらいは所属していたSES内で何かできないか探したりはしていた

テーマ②「実際働いてみてどう?働き方の違いは?」

このテーマではざっくばらんに働き方の違いについてお話ししました。
f:id:krocks96:20220206203552p:plain

  • 全部違う、共通点はオフィスがあることくらい
  • 忙しさは波があるので一概には言えない、SIerの方が開発スパンが長いかも
  • SIerだと人数規模が大きく業務の細分化が進んでいてやることが明確
  • Synamonだと「待っていると何も仕事が振られない」「やることは自分で取りにいく」
  • 最初の2週間くらい不安で辛かったが、自分で手をあげて動いていくことで自分の立ち位置を考えることができた
  • 立ち位置を考えた結果、自分の思いもしなかったところが強みになったりする

テーマ③「SIer経験しておいて良かった~!って思う瞬間」

このテーマではSIerで経験したことが活きている場面についてお話ししました。
f:id:krocks96:20220206210533p:plain

  • (SIerでのポジションにもよるが)要件定義や合意形成といったクライアントワーク
  • 見積を作るときの工数や金額の感覚を得ることが出来た(リスクヘッジで見積のバッファを積みすぎになっているかも)
  • SIerの方が大規模開発だったので、サービスがスケールした時に活きるかもしれない
  • SIerで客先で話す必要があったので傾聴力やコミュニケーション力がついた
  • 組織体制がしっかりしたところにいたので、組織作りをするにあたって経験が活きている

質問コーナー

f:id:krocks96:20220206211336p:plain

じゅーいちさんは東京への移住組と伺っていますが、リモートの仕事文化が定着した現在、東京を出るという選択肢はありますか?

  • 全然ありますね~笑
  • 会社の方針、仕組み次第なところはある
  • 会社に来ても来なくてもいいとなると出社もいいものだなと思うこともある
  • 田舎で働くの憧れません?笑

XR企業に転職してからSIer時代に勉強しておいてよかったと思うことはありますか?

  • 全く業務関係ないところでプログラミングの勉強したり資格試験の勉強したりしていたこと
  • サーバサイドは作ったモノが見えないので、見えるものとしてシェーダーを書いてVRChatにもっていったりしていた
  • UML(クラス図やシーケンス図など)の書き方を学んだこと

XR関連の業務経験がない状態でXR業界に転職するのはなかなかハードルが高いんじゃないかと思いますが、どうやって決断したんでしょうか?

  • 結論としては「やりたかったから覚悟を決めた」になる
  • 面接時点でSynamonの抱えている課題を聞いてやるべきことが見えたのでやれると思った
  • 趣味を仕事にするとつまらなくなるというのが心配だったが、チャンスは今しかないと思って覚悟を決めた
  • iPhoneが出た時に波に乗り損ねた経験があり、XRも同様に時代の変わり目になるのではと思って覚悟を決めた

さいごに

以上、イベントの内容を箇条書き形式でまとめてみました。

ここからは個人の感想です。
まずはじめに、イベントを企画してくださったふわりさん、そして視聴してくださった皆さんありがとうございました。他の方の経験、考えを聞けて非常に興味深かったですし、こうしてパブリックな場で話すことが出来て勉強になりました。次回はもう少し緊張せずに話せたらいいなと思います笑
また、イベント後にアンケートも取らせていただいたのですが「転職時に考えていたことが参考になった」という声や「スタートアップでの仕事の進め方を知ることができてためになった」という声をいただき、開催して良かったなと胸をなでおろしております。

そして全体を通して思ったのは、XR転職に必要なことは「勇気をもって一歩踏み出す」ことではないかということです。パネリストそれぞれで転職に至るまでの道筋は異なりますが、最後の質問への回答でもあったように覚悟を決めて現状を変えるために自らアクションをした結果が現在に繋がっているのかなと思いました。

大きく環境を変えることはリスクもあり難しいものですが、出来ることから少しずつ始めてみてはいかがでしょうか。

簡単に出来ることといえば、Synamonではカジュアル面談を実施しております。

カジュアル面談はMeetyから▼
meety.net

エントリーはこちら▼
herp.careers

また、本テックブログやnote記事のお知らせは、Synamon公式Twitterでも発信もしています。
弊社の取り組みに興味を持っていただけたら、ぜひフォローお願いいたします!
twitter.com

WindowとAndroidでNiantic LightshipのARDK Example Scenesをビルドする

WindowとAndroidでの組み合わせでNiantic light ship ARDKのサンプルシーンをビルドする為の手順を纏めます。
詳しくは公式のガイドを見て頂くのが良いかと思いますが、クイックスタートとして使えるメモ書きがあると便利だなと思い書くことにしました。

ビルド設定以外は駆け足で進めますのでご了承ください。

検証環境

  • Unity 2021.4.34f1
  • ARDK 1.1.0(ardk-1.1.0.unitypackage)
  • ARDK Example Scenes (ardk-examples-1.1.0.unitypackage)
  • Android11 (Xperia 1III)

手順

  1. Unityにて3Dプロジェクトを作成
  2. Build SettingにてPlatformをAndroidにSwitchします。
  3. ardk-1.1.0.unitypackageをImport(メニューより Assets > Import Package)
  4. ardk-examples-1.1.0.unitypackageもImport
  5. サンプルシーンを開く(例:Projectより Meshing > ARDKExamples > ContextAwareness > Meshing)
  6. マルチプレイ機能を使用するサンプルの場合はArdkAuthConfig.assetにライセンスキーを設定する(Meshingなどマルチプレイを伴わないサンプルでは不要)
  7. Build SettingにScenes In Buildにビルドするシーンを追加(既存でシーンが設定されている場合は外す)
  8. Project Settingの Player > Android > Other Setting を以下の様に設定します

f:id:Q1J011:20220126173812p:plain

設定が出来たらビルド! Android端末に入れて動作確認をしてみてください。

書き出してみるとそれほど複雑でもないですし、慣れればさくさく進められると思います。
公式のマニュアルも丁寧に書かれているので疑問点があればぜひ参考にしてみてください。

lightship.dev

GUIにおける状態管理の考え方について

はじめに

エンジニアの松原です。業務以前に個人開発でUnityを触っていたのですが、まずはサードパーティ製ライブラリを取り込んでから開発がスタートするのが多かったと思います。(分かりやすい例として、Oculus IntegrationUltraleap Plugin For Unityを真っ先に入れていた気がしています)

当時の個人開発のアプリではあまりアプリケーションの設計を考えておらず、UnityのScene間でデータをやり取りすることが少なく、何かしらの処理は理由もなく多数のクラスや関数に依存していました。 業務でUnityを使った開発をするようになってからは、サーバーサイドのAPIと連携するようになったため、個人開発でもある程度設計を意識するようになりました。

今回は設計のうち、GUIにおける状態管理に対する考えのパターンについて記事にしてみました。(Unityの話だけでなく、Webフロントエンド開発で使われているトピックも入ってきます)Unityで実際にコードを書くことに関してはまた別の機会で行いたいと思います。

今回の記事の注意として、UnityのAnimator Controllerなどで登場するStateはFSM(Finite State Machine)と呼ばれるステートマシンで、同じ状態を表していますが、扱うトピックが異なるため、今回は登場しません。

なぜGUIに状態管理が必要なのか

Unityのみならず、GUIを扱う場合、以下の課題に遭遇することが多いと思います。

  • ステートレスなサーバーサイドAPIとやり取りした結果をGUIに反映したい
  • 複数のUIのコンポーネントやクラス間で共有したいプロパティがある
  • 画面の切り替え(またはUnityのシーン)の切り替え時に変更したプロパティを維持したい

これらの課題を応急処置的なコードを使って開発をすすめていくと、複雑な依存関係が増えてきます。依存関係が増えるということは状態の扱いが難しくなり、設計の変更も容易でなくなってきます。

そこで状態を管理しているオブジェクトをいくつかの設計パターンに切り出して考えてみます。

状態管理を外部オブジェクトとして設置する(Storeパターン)

共有化したい状態をStoreというグローバルなオブジェクトを利用して管理する方法を紹介します。 こちらのパターンはWebフロントエンド開発のJavaScriptフレームワークであるVueの公式ページで紹介されている状態管理のパターンを参考にしたものになります。

jp.vuejs.org

Vue公式の方ではObserverの記述は省略されているのですが、状態管理にリアクティブなプロパティが利用できる、もしくはStateを監視する仕組みをVueでは暗黙的に利用することが多く、JavaScriptフレームワーク以外で一般的に説明するためObserverを書き加えています。

f:id:fb8r5jymw6fd:20220124005617j:plain:h500

上の図に追加して、State書き換え時の処理ギミックを加えたものが以下の図になります。ここのギミックに関しては実装方針でも変わってきますが、最低限イメージしやすい内容にしています。

初期値の設定まわりは省略していますが、Stateの更新サイクルとしては以下のようになります。

  1. GUIパーツの操作(ボタン押下、スライドの値変更時など)に紐づいたトリガーが発火時、そのトリガーに対応する処理が呼び出される
  2. 処理が実行され、Stateの変更がある場合はStateの変更処理を行う命令を呼び出す
  3. Stateの変更命令を受け取り、保持しているStateを書き換える
  4. Stateの書き換えを検知する
  5. 変更されたStateに依存しているPresenterやViewに対して変更を通知する

f:id:fb8r5jymw6fd:20220124173631j:plain:h500

上記で登場したPresenterやViewは MVC / MVP パターンで登場する概念ですが、Unityで分かりやすい例えを考えてみます。
UnityではuGUIを利用してGUIを組むことが一般的だとは思いますが、Store内でStateが更新されても、画面上に反映するためにはGUIコンポーネントの表示部をスクリプトから更新する必要があります。

下図のTextコンポーネントも同様で、このコンポーネントのTextフィールドに対して直接更新処理をかけないと画面上に変更が反映されません。このように、特定のStateに依存しており、Stateの変更に伴ってState変更処理以外の手続きを行う必要がある部分の実装をViewと捉えると分かりやすいかと思います。このStateの書き換え後のギミックを仲介する役割がObserverとなります。

f:id:fb8r5jymw6fd:20220124175051j:plain:h500

状態管理を行うモダンなアーキテクチャを考える(Fluxパターン)

上記のように状態管理をしつつ、処理の依存関係を極力減らすために、処理の構造を単方向にするFluxというコンセプト(またはアーキテクチャ)があります。 現在はFacebookのGitHubにアーカイブとして残っています。このコンセプトを基に実装・派生したReduxMobXを使うことをFacebookは推奨しています。

github.com

Fluxのコンセプトの実装例として以下のようにまとめることができます。先ほど紹介したStoreパターンではStateの書き換えは外部から参照、命令を呼び出すことで直接書き換えができていましたが、こちらは役割をさらに細分化して処理を単方向に扱えるようにしています。 それぞれ以下の役割を持っています。

  • Action - 具体的な処理を記述するためのパターンで、処理単位のテンプレートとして定義されている。成功や失敗などの状態変更の起点を持つことができる
  • Action Creator - Actionを作成する責務を持つ
  • Dispatcher - Action Creatorから作られたActionをReducerに送る責務を持つ(実装によっては省略されることもある)
  • Reducer - Actionを実際に実行し、Stateを書き換える責務を持つ。StateはReducerからでしか書き換えができない
  • State - 保持したい情報の単位または入れ物
  • Watcher(Observer) - Stateの更新を監視し、依存しているコンポーネントに更新を通知する

f:id:fb8r5jymw6fd:20220124192212j:plain:h500

Fluxの実装によっては定義されている言葉が違うことがありますが、かねがねそれぞれの役割としては上記のようになっていることが多いと思います。 Fluxではより役割を厳格に定めることによって、双方向の依存関係を無くすように設計されたアーキテクチャであるといえると思います。

今回のまとめ

今回はWebフロントエンドで登場する状態管理の考え方をJavaScriptフレームワークで利用されている状態管理のパターンを取り上げました。

これらを実際にUnityで扱うにはUniduxなどがありますが、こちらは画面遷移も取り扱っているため、今回はGUIでの状態管理について解説したかったので、また別の機会に紹介したいと思います。 github.com

また、StoreパターンやFluxパターンは MVC / MVP や MVVM のようにアプリケーションの設計に深く根付いているというより、状態管理という責務分担が難しいものをうまくやりくりするためのコンセプトのようなので、派生形のReduxやMobXもどこかの機会で追ってみたいと思います。