仮想と物理とエトセトラ

xRや物理とかごった煮の備忘録的技術ブログ

Vroid Studioから出力したVRMをHoloLens2で閲覧する

今回は、VRoid Studioで作成したアバターVRM出力し、HoloLens2で閲覧します。

vroid.com

VRoid Studioでは気軽にアバターが作成できるため、VRChatなどで用いられることが多いです。
私もアバターを作成してみたので、試しにHoloLens上で投影し、現実世界に召還してみます。

前提

今回の環境は以下です。

Unity 2019.4.31
MRTK 2.7.3

シーン中でMRTK用のConigureは設定済みとします。
また、VRoid Studioですでにモデルは作成済みとします。

準備

VRoid StudioからVRMファイルを出力する

まずは、VRoid StudioからVRMファイルを取得します。
モデルを開いた後の画面右上真ん中のボタンから、VRMエクスポートを選択します。
f:id:napo909:20220123164915p:plain

VRMエクスポート画面ではエクスポート時の設定を行えます。
ポリゴン数は4万ポリゴン数程度なので問題ないと思いますが、念のため「透明メッシュを削除する」にチェックを入れ、マテリアル数と解像度を削減しておきます。
設定が終わったら「エクスポート」ボタンを押します。
f:id:napo909:20220123165713p:plain

ボタンを押すとVRMの設定画面になります。
必須事項である「タイトル」、「作成者」を入力します。
配布する予定がある場合は、ほかの項目も入力します。
すべて設定が終わったら、一番下の「エクスポート」ボタンを押します。
f:id:napo909:20220123170005p:plain
f:id:napo909:20220123170040p:plain

次に表示されるウィンドウで保存場所を指定したら、VRMファイルの出力は完了です。

VRMファイルをUnityに取り込む

ここで、作成したVRMファイルをUnityに取り込みます。
VRMファイルは通常ではUnityに取り込むことができません。
そこで、UnityにVRMファイルを取り込むことを可能にする、UniVRMを使用します。
このアセットを使用すると、VRMを取り込み、Unityで使用できるPrefab化することができます。
下記リンクからUniVRM-[バージョン名].unitypackageをダウンロードします。
github.com

f:id:napo909:20220123170442p:plain

ダウンロードしたUnityPackageをUnityのProject Windowドラッグ&ドロップします。
ドラッグ&ドロップすると、Import Unity Package Windowが表示されるので、下端のImportボタンを押します。

Importが終わると、おすすめの設定をするように指示されるため、Accept Allで実行します。
f:id:napo909:20220123171259p:plain

Console Windowにエラーが出ていますが、Editor上で使用するGlb Importerが複数あるため発生しているものです。
アプリ実行には特に問題ないため、無視して問題ありません。
f:id:napo909:20220123171537p:plain

設定が終わると、上部メニューにVRM0が追加されます。
Import from VRM 0.xを選択することでVRMファイルを読み込むことができます。
最初にVRMファイルを読み込み、次にAsstsのどこに出力するか指定します。
Assetsフォルダ配下でフォルダを作成し、その中を出力先にすると散らからずに済みます。
f:id:napo909:20220123171739p:plain

f:id:napo909:20220123171843p:plain

正常に処理が終わると、出力先に指定したフォルダにVRMモデルから生成したPrefabが生成されます。
これで、Unity上でVRMモデルを取り扱えます。
試しにHierarchyにドラッグ&ドロップすると、Scene上に表示されます。
f:id:napo909:20220123172347p:plain

アニメーションを設定する

出力したモデルはそのままではTポーズをしているだけで味気ないので、アニメーションをさせます。
今回は、下記URLのUnity Animationを使用させていただきました。

booth.pm

ダウンロードしたファイルを解凍するとEmoteSet_Free_v130.unitypackageが入っているため、先ほどと同様にProject Windowドラッグ&ドロップします。
ドラッグ&ドロップするとImport Unity Pakcage Windowが表示されるので、Importボタンを押します。
f:id:napo909:20220123173257p:plain

正常にImportされると、Assets/Necocoyaフォルダが作成され、その中にAnimation用のファイルが配置されます。
f:id:napo909:20220123173611p:plain

今回は、Emote02/OneLoopDivisionのAnimation Contollerを使用します。
Animation Controllerをダブルクリックすると、Animation Windowが表示されるので、Parametersタブから使用したいアニメーションを選択します。今回は01_Tefuri3_OneLoopを選択します。
f:id:napo909:20220123174117p:plain

アニメーションがどのような動きをするかは、animファイルを選択した状態でInspector Windowの下端の再生ボタンから確認できます。
f:id:napo909:20220123174102p:plain

作成したモデルへのAnimation Controllerの適用は、モデルを選択した状態でInspector Window中のAnimatorコンポーネントControllerを設定することで実現できます。
f:id:napo909:20220123174356p:plain

そのままではモデル表示位置が初期状態の頭の位置と同じなので位置を微調整します。 また、つかんで移動できるように、Object ManipulatorCapsule Colliderをアタッチすれば準備完了です。 f:id:napo909:20220123175716p:plain

動作確認

無事、HoloLensで現実世界に投影することができました。
拡縮もできます。
VRM/MToonシェーダもSingle Pass Instancedに対応しているようで、両目でしっかり見えます。

Netcode for GameObjects (旧MLAPI)をHoloLensで使ってみる その2

今回は前回の続きです。

xr-physics-work-etc.hatenablog.com

前回、Hostとして使用したHoloLens2の頭位置は共有されましたが、Clientとして接続したUnityEditorでは共有できませんでした。
この問題を解消します。

下記記事によると、以前のMLAPIからの変更点として、NetworkTransformでは、Server側からのTransform共有ができないようです。
Client側から共有する方法として、ClientNetworkTransformを用いる方法があるようです。

xrdnk.hateblo.jp

今回は下記を元にClientNetworkTransformを用いてClient側からも頭の位置を共有できるようにします。

docs-multiplayer.unity3d.com

前提

今回の環境は以下です。

Unity 2020.3.16
MRTK 2.7.3
Netcode for GameObjects 1.0.0-pre.4

準備

まずは、ClientNetworkTransformを用意します。
ClientNetworkTransformはnet code for GameObjectsの標準APIとしては存在しません。
サンプルとして用意されているため、まずはそれを導入します。

Unity上部メニューの「Window」→「Package Manager」からPackage Managerウィンドウを開きます。
f:id:napo909:20220116155345p:plain

Package Managerウィンドウから、「Netcode for GameObjects」を選択すると左欄に「Samples」という項目があります。
「Samples」の文字列をクリックすると用意されているサンプルが展開されます。
そこに「ClientNetwork Transform」があるので、Importボタンを押して取得します。
f:id:napo909:20220116155625p:plain

正常に導入できると、Assets/Samples/Netcode for GameObjects/1.0.0-pre.4ClientNetworkTransformフォルダが作成されています。
f:id:napo909:20220116160337p:plain

ClientNetworkTransform/Scriptsフォルダ内にClientNetworkTransform.csがあります。
ClientNetworkTransform.csを見ると、以下の記載がありました。

クライアント側の変更に伴うtransformの同期に使用します。これにはホストも含まれます。所有者としての純粋なサーバーは、これではサポートされていません。常にサーバーが所有するようなトランスフォームには NetworkTransform を使用してください。 (Deepl翻訳)

github.com

これは、L34にあるように、サーバ側にクライアントが所有しているオブジェクトのTransformを送り、サーバ側で処理しているためです。
サーバ用アプリを用意する場合は、NetworkTransform、ホスト、クライアントで用いる場合はClientNetworkTransformを使うのがよさそうです。

ユーザ位置はサーバ側アプリで使用しないため、Playerプレハブにアタッチするコンポーネントを、ClientNetworkTrnasformに変更しました。

f:id:napo909:20220116171811p:plain

HoloLens→PC接続

PCではUnityEditorからInspectorを用いて接続先IPを設定できましたが、HoloLensではそうもいきません。
そのため、HoloLensをClientとしてHostであるPCに接続するために、InputFieldを用いて接続先IPを設定する口を用意しました。
f:id:napo909:20220116172013p:plain

前回使用したNetworkConnectButtonFunctions.csを改修し、Input Filedが更新された際にIPアドレスとして設定されるようにします。

  • NetworkConnectButtonFunctions.cs
クリックで展開
using UnityEngine;
using Unity.Netcode;
using Unity.Netcode.Transports.UNET;
public class NetworkConnectButtonFunctions : MonoBehaviour
{
    /// <summary>
    /// ネットワークマネージャ
    /// </summary>
    private NetworkManager networkManager;


    void Start()
    {
        // ネットワークマネージャインスタンス取得
        networkManager = NetworkManager.Singleton;
        if(networkManager == null)
        {
            this.gameObject.SetActive(false);
        }
    }

    /// <summary>
    /// ホストとして接続
    /// </summary>
    public void ConnectAsHost()
    {
        networkManager.StartHost();
    }

    /// <summary>
    /// サーバとして接続
    /// </summary>
    public void ConnectAsServer()
    {
        networkManager.StartServer();
    }

    /// <summary>
    /// クライアントとして接続
    /// </summary>
    public void ConnectAsClient()
    {
        networkManager.StartClient();
    }

    /// <summary>
    /// 接続切断
    /// </summary>
    public void Disconnect()
    {
        networkManager.Shutdown();
    }

    /// <summary>
    /// 接続先設定 <-------追加箇所
    /// </summary>
    /// <param name="ipString"></param>
    public void SetIP(string ipString)
    {
        networkManager.gameObject.GetComponent<UNetTransport>().ConnectAddress = ipString;
    }
}

f:id:napo909:20220116172143p:plain

動作確認

今回は、PC側をHost (Server + Client), HoloLens側をClientで接続しました。
PCでHost接続後、HoloLensからClient接続しています。
f:id:napo909:20220116172430g:plain

ClientNetworkTransform.csを用いることで、Clientの動きもHost (Server)側から確認することができました。
これで、HostもClientもお互いの動きを確認できます。

次回は、共有で重要な同じ物体をHost、Clinetで動かし、位置を共有することを試します。

Netcode for GameObjects (旧MLAPI)をHoloLensで使ってみる その1

今回は、Unity公式の共有フレームワークのNetcode for GameObjectsを触ってみます。

docs-multiplayer.unity3d.com

元になったMLAPIについては以前触れていますが、v.0.1.0からv.1.0.0になって変更点があると思われるので、確認の意味も込めて触れてみます。

xr-physics-work-etc.hatenablog.com

前提

Netcode for GameObjectsではUnity 2020.3, 2021.1, and 2021.2を推奨しているので、以下を使用します。

Unity 2020.3.16
MRTK 2.7.3

MRTKの導入~ HoloLensアプリ向けの設定は下記を参考にできます。

bluebirdofoz.hatenablog.com

Netcode for GameObjectsを導入する

公式のチュートリアルを元に実施します。

docs-multiplayer.unity3d.com

上部メニューのWindow→Pacakge ManagerからPackage Managerウィンドウを表示します。
f:id:napo909:20220109145039p:plain

Pakcage Managerウィンドウ左上の+ボタンを押して、Add package from git URL...を選択します。

f:id:napo909:20220109145502p:plain

出てくるInputFieldに下記文字列を入力してAddボタンを押します。
com.unity.netcode.gameobjects

f:id:napo909:20220109150233p:plain

正常に読み込まれると、リストにNetcode for GameObjectsが追加されます。
f:id:napo909:20220109150418p:plain

Packageを見てNetcode for GameObjectsフォルダが存在すれば正しく取り込まれています。
f:id:napo909:20220109151522p:plain

お試し実装

チュートリアルHello Worldをベースに、お試しで実装してみます。

まずはユーザを示すPrefabを作成します。
Scene上にSphereを追加し、NetworkObjectコンポーネントをアタッチします。
方向がわかるようにz方向のScaleを変更しておきます。
f:id:napo909:20220109152739p:plain

次に、ユーザ頭位置を示すようにMLAPIの際に使用したスクリプトを一部修正して作成し、アタッチします。
合わせて、Tramsformを共有対象とする、NetworkTransform もアタッチします。

xr-physics-work-etc.hatenablog.com

  • PlayerTracking.cs
クリックで展開
using UnityEngine;
using Unity.Netcode;
public class PlayerTracking : NetworkBehaviour
{

    // Update is called once per frame
    void Update()
    {
        if(IsOwner)
        {
            // 自オブジェクトの場合
            SetPlayerTransform();
        }


    }

    /// <summary>
    /// プレイヤー位置設定関数
    /// </summary>
    void SetPlayerTransform()
    {
        // カメラ位置にオブジェクトを移動
        this.transform.position = Camera.main.transform.position;
        this.transform.rotation = Camera.main.transform.rotation;
    }
}

f:id:napo909:20220109153627p:plain

作成したGameObjectをPlayerに名称を変更し、Assets中にドラッグ&ドロップしてPrefab化します。
Scene上のPlayer GameObjectは削除します。
f:id:napo909:20220109154327p:plain

次に、Scene上に空のGameObjectを作成し、NetworkManagerに名前を変更します。
作成したGameObjectにNetworkManagerコンポーネントをアタッチします。
f:id:napo909:20220109154424p:plain f:id:napo909:20220109154451p:plain

NetworkManagerコンポーネントのNetwork TransportプルダウンメニューからUNetTransportを選択します。
f:id:napo909:20220109154624p:plain

Network Prefabsリストのプラスボタンを押して、先ほど作成したPlayer Prefabを設定します。
また、Player Prefabの箇所にも同様に設定します。
f:id:napo909:20220109154934p:plain f:id:napo909:20220109154821p:plain

HoloLensからネットワーク接続するためのボタンを以前の記事を参考に作成します。
ボタンの配置など設定は下記と同じため参照して実施します。
xr-physics-work-etc.hatenablog.com HoloLens用の接続用ボタンを用意する

  • NetworkConnectButtonFunctions.cs
クリックで展開
using UnityEngine;
using Unity.Netcode;

public class NetworkConnectButtonFunctions : MonoBehaviour
{
    /// <summary>
    /// ネットワークマネージャ
    /// </summary>
    private NetworkManager networkManager;


    void Start()
    {
        // ネットワークマネージャインスタンス取得
        networkManager = NetworkManager.Singleton;
        if(networkManager == null)
        {
            this.gameObject.SetActive(false);
        }
    }

    /// <summary>
    /// ホストとして接続
    /// </summary>
    public void ConnectAsHost()
    {
        networkManager.StartHost();
    }

    /// <summary>
    /// サーバとして接続
    /// </summary>
    public void ConnectAsServer()
    {
        networkManager.StartServer();
    }

    /// <summary>
    /// クライアントとして接続
    /// </summary>
    public void ConnectAsClient()
    {
        networkManager.StartClient();
    }

    /// <summary>
    /// 接続切断
    /// </summary>
    public void Disconnect()
    {
        networkManager.Shutdown();
    }
}

f:id:napo909:20220109160933p:plain

プロジェクトをビルドする前に「Build Settings」→「Player Settings」→「Player」→「Publishing Settings」→「Capabilities」から下記にチェックを付けます。

  • InternetClientServer
  • PrivateNetworkClientServer

f:id:napo909:20210711120536p:plain

その後、ビルドを実施し、HoloLens2にアプリを入れます。

動作確認

PC-HoloLens間で動作確認します。
方法はMLAPIの時と同じです。

HoloLens2でアプリを起動したら、自分のIPアドレスを確認します。 (「自分のIP」のボイスコマンドやWi-Fiの詳細情報を確認)

確認したHoloLens2のIPアドレスをPC側のNetworkManagerオブジェクトのUNET TransportConnect Addressに設定します。

f:id:napo909:20220109163547p:plain

その後、HoloLens側でConnect As Host、PC側でConnect As Clientボタンを押して接続します。
正しく接続できると、各ユーザの頭の位置が球体で示されます。
HoloLens2をかぶっている頭を動かすと、PC側にも反映されます。

f:id:napo909:20220109163824g:plain

ただし、前回と異なりPC側(Client側)の頭位置が動いていませんでした。
※IsOwnerの扱いがMLAPIと異なってる?
この点は後日調査します。

MRTK(2.7.2)のExampleを試す その4 (Demos - Gltf)

今回は下記の続きです。

xr-physics-work-etc.hatenablog.com

前提

今回の前提は以下です。
Unity 2019.4.17f1
MRTK 2.7.2

準備

いつものようにPackage Managerからデモをインポートします。
f:id:napo909:20211219102128p:plain

Glb-Loading-Demo

このシーンは、インターネット上にあるglbモデルをUnityで取り扱えるオブジェクトとして表示するデモです。
f:id:napo909:20211219102800p:plain

glbまたはgltfは、JSONを用いて3Dモデルなどを表現する形式です。
標準のUnityでは動的読み込みなどできませんが、MRTKのGltf Importerを用いることで実現できます。

ja.wikipedia.org

GltfUtility.cs

このスクリプトで、gltfまたはglb形式のモデルデータを読み込み、Scene上に表示することができます。

github.com

staticなクラスのため、基本的にスクリプト中から使用することが前提です。
主な使い方の流れは以下です。

[1] 下記メソッドの中から適したものを使用してGltfObjectを取得する。

・ GetGltfObjectFromGlb(Byte[])
    glbファイルのバイト列からGltfObjectを取得する。  
・ GetGltfObjectFromJson(String)  
    Jsonファイルの内容(文字列)からGltfObjectを取得する。  
・ ImportGltfObjectFromPathAsync(String)
    ファイルパスからGltfObjectを取得する。(gltf, glbファイル両対応)  

[2] 取得したGltfObjectから下記メソッドをどちらか実施することで、Scene上にGltfオブジェクトを元にしたGameObjectを表示できる。

・ Construct()  
・ ConstructAsync()  

Rest.cs

このスクリプトは、直接Gltfのデモとして関係しているわけではないですが、初見のため取り扱っておきます。
このスクリプトに含まれるメソッドを使用することで、REST APIを用いてPOST, GETが実施できます。

github.com

staticなクラスのため、基本的にスクリプト中から使用することが前提です。
下記がよく使用されると思われるメソッドです。

  • GetAsync
    Getリクエストを送る場合に使用するメソッド。
    引数:
    query : URLを入力  
    headers : リクエストに使用するオプションのヘッダ  (オプション)  
    timeout : タイムアウト時間  (オプション)  
    downloadHandler : ダウンロード時に使用するオプションのハンドラ  (オプション)  
    readResponseData : ダウンロードハンドラの使用有無  (オプション)  
    certificateHandler : 証明書検証に使用するハンドラ  (オプション)  
    disposeCertificateHandlerOnDispose : UnityRequest破棄時に証明書検証ハンドラを破棄するか否か  (オプション)   
  • PostAsync
    POSTリクエストを送る場合に使用するメソッド。
    引数:
    query : URLを入力  
    formData : POSTするWWForm型のForm Data(※)  
    jsonData : POSTするJsonデータ(※)
    bodyData : POSTするbyte列のデータ(※)  
    headers : リクエストに使用するオプションのヘッダ  (オプション)  
    timeout : タイムアウト時間  (オプション)  
    readResponseData : ダウンロードハンドラの使用有無  (オプション)  
    certificateHandler : 証明書検証に使用するハンドラ  (オプション)  
    disposeCertificateHandlerOnDispose : UnityRequest破棄時に証明書検証ハンドラを破棄するか否か  (オプション)   
    (※):オーバーロードされているため、どれか1つまたは使用しない  
  • PutAsync
    PUTリクエストを送る場合に使用するメソッド。
    引数:
    query : URLを入力  
    jsonData : PUTするJsonデータ(※)
    bodyData : PUTするbyte列のデータ(※)  
    headers : リクエストに使用するオプションのヘッダ  (オプション)  
    timeout : タイムアウト時間  (オプション)  
    readResponseData : ダウンロードハンドラの使用有無  (オプション)  
    certificateHandler : 証明書検証に使用するハンドラ  (オプション)  
    disposeCertificateHandlerOnDispose : UnityRequest破棄時に証明書検証ハンドラを破棄するか否か  (オプション)   
    (※):オーバーロードされているため、どれか1つ使用する  
  • DeleteAsync
    DELETEリクエストを送る場合に使用するメソッド。
    引数:
    query : URLを入力  
    headers : リクエストに使用するオプションのヘッダ  (オプション)  
    timeout : タイムアウト時間  (オプション)  
    readResponseData : ダウンロードハンドラの使用有無  (オプション)  
    certificateHandler : 証明書検証に使用するハンドラ  (オプション)  
    disposeCertificateHandlerOnDispose : UnityRequest破棄時に証明書検証ハンドラを破棄するか否か  (オプション)   

Gltf-Loading-Demo

このシーンでは、ローカルファイルからglbモデルを読み込んで表示するデモです。
f:id:napo909:20211219112934p:plain
デモを正しく実行するには、Assetディレクトリ中にStreamingAssetsディレクトリを作成し、デモ用ディレクトリ中のModelsをコピーする必要があります。
コピーをするには、サンプルシーン中のGltfExampleオブジェクトにアタッチされている、TestGltfLoadingコンポーネントに付与されているボタンを押下すると、コピーが実施できます。
正常にファイルが配置できると、表示されている警告が消えます。
f:id:napo909:20211219112836p:plain

そのあと、Unity上で実行するとglbモデルから構成されたアボカドがシーン上に表示されます。

使用しているスクリプトは、先ほど紹介したGltfUtility.csのImportGltfObjectFromPathAsyncで共通しているため省略します。

キリが良いので今回はここまで。
次回はHandCoachのデモを取り扱います。

HoloLens2でJoyConのIMUを使ってみたかった(失敗)

今回はNintendo SwitchのJoyConをHoloLensで使用できるか試します。
使用できれば、加速度、ジャイロセンサを用いて何かしらできそうです。
※今回の記事はHoloLens上で正しく動作できていません。後々解決策がわかったら記事にします。

JoyConをUnityで取り扱う方法については下記を参考に実施します。

baba-s.hatenablog.com

前提

今回は下記環境で検証しています。
MRTKのインポートなどの設定は今回は省略し、JoyconLibの導入から始めます。
Unity 2019.4.17
MRTK 2.7.2
JoyconLib 0.6

準備

まずはJoyconLibのUnityPackageを下記からダウンロードします。

github.com

f:id:napo909:20211212163646p:plain

ダウンロードしたUnityPackageをUnity上にドラッグ&ドロップすると、Unity Packageのインポートができます。
右下の「Import」ボタンを押下するとインポートできます。
※ Sceneフォルダに警告が出ていますが、特に問題ないので無視でよいです。
f:id:napo909:20211212163917p:plain

正常にインポートができると、JoyconLib由来のファイルがAssetsフォルダ上に配置されます。
f:id:napo909:20211212164151p:plain

そのままだとエラーが発生するため、参考元の記事の通り、一部ソースコードを修正します。

  • Joycon.cs L370
    変更前:
DebugPrint(string.Format("Dequeue. Queue length: {0:d}. Packet ID: {1:X2}. Timestamp: {2:X2}. Lag to dequeue: {3:s}. Lag between packets (expect 15ms): {4:s}",

変更後:

DebugPrint(string.Format("Dequeue. Queue length: {0:d}. Packet ID: {1:X2}. Timestamp: {2:X2}. Lag to dequeue: {3:t}. Lag between packets (expect 15ms): {4:g}",

f:id:napo909:20211212165259p:plain

Scenes/Scene1を選択すると、JoyconLabのサンプルが確認できます。
これを左上メニューのFile/Save As...から複製して保存します。
f:id:napo909:20211212165814p:plain

複製したSceneをHoloLens用に構成します。
左上メニューのMixed Reality/Add to Scene and Configure...からMRTK用に構成します。
f:id:napo909:20211212165937p:plain

そのままだとJoyConの動きを示すCubeが頭の位置に来てしまうため、微調整します。
f:id:napo909:20211212170152p:plain

Scene上にTextを配置して、ジャイロと加速度の状態を確認できるようにします。
TextMeshProを適当な位置に配置して、JoyconManagerにShowJoyConState.cs (下記ソース参照)をアタッチし、TextMeshProを参照させます。

  • ShowJoyConState.cs
クリックで展開
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
public class ShowJoyConState : MonoBehaviour
{
    private List<Joycon> joycons;

    [SerializeField]
    private TextMeshPro text;

    // Start is called before the first frame update
    void Start()
    {
        this.joycons = JoyconManager.Instance.j;
    }

    // Update is called once per frame
    void Update()
    {
        ShowState();
    }

    private void ShowState()
    {
        string info = "";

        foreach(var joycon in this.joycons)
        {
            info += "#########\n";
            info += (joycon.isLeft) ? ("[Left]\n") : ("[Right]\n");
            info += $"Accel:\n";
            info += $"x:{joycon.GetAccel().x}\n y:{joycon.GetAccel().y}\n z:{joycon.GetAccel().z}\n";
            info += $"Gyro:\n";
            info += $"x:{joycon.GetGyro().x}\n y:{joycon.GetGyro().y}\n z:{joycon.GetGyro().z}\n";
            info += "#########\n";
        }

        this.text.SetText(info);
        
    }
}

f:id:napo909:20211212171722p:plain
f:id:napo909:20211212171859p:plain

ProjectSettins/PlayerのCapabilitiesからBlueToothにチェックを入れておきます。
f:id:napo909:20211212172520p:plain

BuildSettingsからビルド対象シーンに今のシーンを追加し、Buildボタンを押します。
f:id:napo909:20211212172219p:plain

次にHoloLens側でBluetoothを用いてJoyconを接続します。
設定/Bluetoothとその他のデバイスからBluetoothまたはその他のデバイスを追加するを選択します。
f:id:napo909:20211212175620p:plain

追加するデバイス種として、Bluetoothを選択します。
f:id:napo909:20211212175737p:plain

Joyconの丸いボタンを長押ししペアリングモードにすると、JoyConが一覧に表示されます。選択すると、HoloLensとJoyConをBluetooth接続できます。
f:id:napo909:20211212180044p:plain

動作確認

HoloLens側でアプリ起動しましたが、JoyConの加速度、ジャイロのデータを取得することはできませんでした。
Unity上では動作確認できているため、HoloLens特有の問題のようです。

f:id:napo909:20211212180936g:plain

アプリのログを見たところ、使用しているdllが読み込めていないようです。

  • UnityPlayer.log
DllNotFoundException: Unable to load DLL 'hidapi': The specified module could not be found.
  at JoyconManager.Awake () [0x00000] in <00000000000000000000000000000000>:0 
 
(Filename: currently not available on il2cpp Line: -1)

該当のプラグインの格納場所を見ると、win32, win64, mac用のプラグインしかなく、arm, arm64用のプラグインが入っていないようです。
hidapiのarm用プラグインがあれば、動作しそうです。
f:id:napo909:20211212180449p:plain

うまくいってはいないですが、今回はここまで。
hidapiのarm版が見つかったら再度チャレンジしてみます。

MRTK(2.7.2)のExampleを試す その3 (EyeTracking)

今回は前回の続きです。

xr-physics-work-etc.hatenablog.com

前提

今回の前提は以下です。
Unity 2019.4.17f1
MRTK 2.7.2

準備

前回と同じようにPackage Managerから対象のデモをImportします。
f:id:napo909:20211205135836p:plain

EyeTrackingDemo-00-RootScene

このSceneはEyeTrackingの各デモに遷移するためのSceneです。 f:id:napo909:20211205141810p:plain

EyeTrackingのデモでは、Gaze SettingsにEyeGazeCursorが設定されており、視線が何を指しているか確認できるようになっています。

f:id:napo909:20211205151114p:plain

EyeCalibrationChecker

デモ用のスクリプトですが、使いまわしがききそうなので、EyeCalibrationCheckerを取り扱います。
このスクリプトでは、HoloLensのEye Trackingのキャリブレーションが済んでいるかどうかで、アプリ起動時またはキャリブレーションを実施したタイミングで実行するUnityEventを切り替えることができます。
HoloLensでは、アプリ内からキャリブレーションを実施して戻ってくる、ということもあるので、Eye Trackingに関する設定を行う場合は、キャリブレーションが済んだタイミングで設定などを切り替える必要があります。

EyeCalibrationCheckerではInspector上から下記設定が行えます。

f:id:napo909:20211205142812p:plain

EyeTrackingDemo-01-BasicSetup

このデモでは、視線に追従する紫色のカーソルと、物体に視線を合わせ、タップすることで視線で物体を選択できることを試すことができます。

f:id:napo909:20211205150706p:plain

FollowEyeGazeGazeProvider

このスクリプトでは、アタッチしたオブジェクトの位置を視線でポイントしている場所に移動させることができます。
視線で何をポイントしているか、強調することができます。

Inspector上で設定できるパラメタは以下です。

  • defaultDistanceInMeters
    自分とFollowEyeGazeGazeProviderをアタッチしたオブジェクトとの距離。デフォルト値は2m

f:id:napo909:20211205155934p:plain

ColorTap

このスクリプトでは、アタッチしたオブジェクトのマテリアル色をHover, Selectしたときに変更することができます。
色を変えることで、選択できているか否か、明確にすることができます。

Inspector上で設定できるパラメタは以下です。

  • tapAction
    対象とするInputAction。選択であれば、Selectを設定する。デフォルト値はNone

  • color_IdleState
    通常時(未選択)の時に設定される色。デフォルト値はColor.cyan

  • color_OnHover
    Hover(Hand rayや視線などでポイントする)した際に変更する色。デフォルト値はColor.white

  • color_OnSelect
    tapActionに設定したものを物体に対して実行した場合に変更する色。(Selectの場合はタップ操作)デフォルト値はColor.blue

f:id:napo909:20211205160020p:plain

EyeTrackingDemo-02-TargetSelection

このデモでは、視線を合わせた際に物体に実行させることができる挙動を確認できます。
視線を合わせたり、視線を合わせた状態でタップ操作をすることで物体操作が遠距離で実施できます。

f:id:napo909:20211205153521p:plain

EyeTrackingTarget

このスクリプトでは、自オブジェクトに対して視線が当たっている際に行う動作を設定できます。
視線の操作だけでなく、ボイスコマンドにも紐づけることできます。
Inspector上で設定できるパラメタは以下です。

  • Select Action
    対象とするInputAction。選択であれば、Selectを設定する。デフォルト値はNone

  • Voice Select
    視線が合っているときに有効になるボイスコマンド。ボイスコマンドを実行することでOnSelectedが発火する。

  • Dwel Time In Sec
    OnEyeFocusDwellが発火するために視線を当て続ける必要のある時間。

  • On Look At Start
    視線を合わせ始めた際に実行されるイベント

  • While Lokking At Target
    視線を合わせ続けているときに毎フレーム実行されるイベント

  • On Look Away
    ターゲットから視線を外した際に実行されるイベント

  • On Dwell
    Dwel Time In Secで設定した時間の間視線を合わせ続けると発生するイベント。(1回のみ)

  • On Selected
    視線を合わせつつ、タップやボイスコマンドで発火させることができるイベント。

  • On Tap Down
    RaiseEventManually_TapDownが呼ばれた際に実行されるイベント

  • On Tap Up
    RaiseEventManually_TapUpが呼ばれた際に実行されるイベント

RaiseEventManually_TapUp, RaiseEventManually_TapDownについては情報があまり見つからず、実際にどのタイミングで発火するか不明瞭。

f:id:napo909:20211205154026p:plain

EyeTrackingDemo-03-Navigation

このデモでは、テクスチャの拡縮、移動を実施できるPanZoomTextureや、スクロールを実施できるScrollRectを視線を合わせることで発火させることができます。

f:id:napo909:20211205160119p:plain

OnLookAtRotateByEyeGaze

このスクリプトでは、アタッチしたオブジェクトに視線が当たっている間、物体を回転させることができます。
BaseEyeFocusHandlerを継承しており、OnEyeFocusStayをオーバライドすることで視線が当たった際の動作を設定しています。
Inspector上で設定できるパラメタは以下です。

  • Focus Enabled
    Focusが有効かどうか設定できる(BaseFocusHandlerからの継承)

  • Time To Trigger Dwell In Sec
    Dwellを発火させるために必要なFocus時間(BaseEyeFocusHandlerからの継承)

  • Speed X, Y
    それぞれの軸の回転速度。(0の場合は回転しない)

  • Inverse X, Y
    それぞれの軸の回転方向を反転させるか否か

  • Rotation Thresh In Degrees
    少しの回転を繰り返さないようにするための閾値

  • Min Rot X, Y
    最小回転角

  • Max Rot X, Y
    最大回転角

f:id:napo909:20211205162547p:plain

EyeTrackingDemo-04-TargetPositioning

このデモでは、視線を合わせることで物体を選択し、タップすることで移動させることができます。
キューブや、スライダを視線とタップ操作だけで操作することができます。

f:id:napo909:20211205164013p:plain

MoveObjByEyeGaze

このスクリプトでは、アタッチしたオブジェクトに視線が当たっている間、物体を移動させることができます。
移動させることのできる軸や、移動量を制限することができます。

  • Use Eye Supported Target Placement
    視線で物体配置を有効化するかどうかの設定

  • Min Look Away Dist To Enable Eye Warp
    ※確認中※

  • Hand Input Enabled
    移動を音声のみで行う場合は、falseにする

  • Handmapping
    手の移動量の何倍の動きを物体にさせるか

  • Delta Hand Movem Thresh
    手の動きを有効にする閾値

  • Transparency_in Transition
    ドラッグしている間のターゲットの透明度設定

  • Transparency_preview
    プレビューをドラッグしている間のターゲットの透明度設定

  • Preview Placem Dist Thresh
    ※確認中※

  • Freeze X, Y, Z
    動きを制約する軸方向

  • Local Min Max_X, Y, Z
    各軸の移動量の制約

  • Placement Surface
    配置する平面の方向(水平か、垂直か)

  • Audio_On Drag Start
    ドラッグ開始時の音

  • Audio_On Drag stop
    ドラッグ停止時の音

  • Voice Action_Put This
    ドラッグ開始に使用するInputAction(音声コマンド用)

  • Voice Action_Over Here
    ドラッグ終了時に使用するInputAction(音声コマンド用)

  • On Drag Start
    ドラッグ開始時に発生させるイベント

  • On Drop
    ドラッグ終了時に発生させるイベント

  • User as Slider
    スライダとして使用するか否か

  • Txt Output_slider Value
    スライダ位置を表示するためのTextMeshオブジェクト

  • Slider_snap To Neareset Decimal
    スライダの場合の刻み幅

f:id:napo909:20211205164415p:plain

EyeTrackingDemo-05-Visualizer

このデモでは視線の当たった箇所が熱源のように、ヒートマップを表示するデモです。
視線の軌跡を可視化することができます。

f:id:napo909:20211205170837p:plain

このデモでは、InteractableEyeTrackingTargetを組み合わせることで、Interactableのアタッチされたオブジェクトに視線を与えてタップ動作をするだけでOnClickを発火させることができます。

f:id:napo909:20211205171626p:plain

DrawOnTexture

このスクリプトでは、視線の当たった位置に、Tableとして設定したTextureから取得した色を設定できるものです。
EyeTrackingTarget::LookedAtPointを使用して視線の当たった位置の座標を取得することで、視線が当たった位置の色を変更しています。
Inspector上で設定できるパラメタは以下です。

  • Heatmap Look Up Table
    ヒートマップ(描画する色)をTextureとして設定する

  • Draw Brush Size
    ヒートマップで色を変更する範囲のサイズ

  • Draw Intensity
    ヒートマップの最大強度

  • Min Thresh Delta Heat Map
    ヒートマップ表示のための閾値

  • Use Live Input Stream
    ヒートマップの結果をすぐに表示するか否か

  • Heatmap Overlay Material Templete
    ヒートマップ描画前のベースのmaterial

f:id:napo909:20211205172738p:plain

今回はここまでです。
次回はGltfのデモを確認します。

MRTK(2.7.2)のExampleを試す その2 (Boundary, Diagnostics)

今回は前回の続きです。

xr-physics-work-etc.hatenablog.com

前提

今回の前提は以下です。
Unity 2019.4.17f1
MRTK 2.7.2

準備

前回と同じようにPackage Managerから対象のデモをImportします。
f:id:napo909:20211128170127p:plain

Boundary Visualization Example

このサンプルでは、PlayAreaなどを視覚的に表示することができます。(VR向けのため、HoloLensでは動作していないと思われる)
f:id:napo909:20211128180644p:plain

CoreServices.csを介してIMixedRealityBoundarySystemを操作することで、表示/非表示を切り替えています。

f:id:napo909:20211128172812p:plain

有効/無効を切り替える対象であるBoundsry Visualizationについては下記に記載があります。

docs.microsoft.com

### 詳細は、VR機器で試すことができた際に追記 ###

DiagnosticsDemo

このサンプルでは、アプリの状態を示すDiagnosticの機能を表示/非表示にできるサンプルです。
DiagnosticDemoControls.csが使用されているかのような記載がScene上にありますが、該当するスクリプトは見つけられず。。。記載が古い?

f:id:napo909:20211128173716p:plain

Diagnostics自体はMixedRealityToolkitDiagnostics Profileから有効/無効の設定ができます。

f:id:napo909:20211128174454p:plain

Diagnosticsは、シーン実施中にMixedRealityPlayspace配下に現れます。
Diagnosticsには2つのコンポーネントがアタッチされています。

  • DiagnosticsSystemVoiceControls.cs
    下記2種のボイスコマンドで有効/無効を切り替えることができる。

    • toggle diagnostics
      診断システムの有効/無効を切り替える。(無効の場合、Profilerも非表示になる)
    • toggle profiler
      CPU使用率などのProfile情報の表示/非表示を切り替える。
  • MixedRealityToolkitVisualProfiler.cs
    CPU使用率などのProfile情報を表示するためのコンポーネント
    基本的にはカスタマイズすることはないと思われる。

f:id:napo909:20211128174823p:plain

今回はいつになく内容が薄いですが、キリが良いので今回はここまで。
次回はEyeTrackingのサンプルを取り扱います。