次の方法で共有


Unityでのローカル アンカー転送

ローカル アンカー転送を使用すると、1 つの HoloLens デバイスが 2 つ目の HoloLens デバイスによってインポートされるアンカーをエクスポートできます。

注:

iOS および Android デバイスは、この方法ではサポートされていません。

SpatialPerception 機能の設定

アプリが空間アンカーを転送するには、 SpatialPerception 機能を有効にする必要があります。

SpatialPerception 機能を有効にする方法:

  1. Unity エディターで、[プレイヤーの設定] ウィンドウを開きます ([プロジェクト設定の編集] > [プレーヤー] >)
  2. [Windows ストア] タブをクリックします
  3. [発行設定] を展開し、[機能] リストの [SpatialPerception] 機能をチェックします

注:

Unity プロジェクトを Visual Studio ソリューションに既にエクスポートしている場合は、新しいフォルダーにエクスポートするか、Visual Studio の AppxManifest でこの機能を手動で設定する必要があります。

アンカー転送

Namespace:UnityEngine.XR.WSA.Sharing
: WorldAnchorTransferBatch

WorldAnchor を転送するには、転送するアンカーを確立する必要があります。 1 人の HoloLens のユーザーが自分の環境をスキャンし、手動またはプログラムで空間内のポイントを共有エクスペリエンスのアンカーとして選択します。 その後、このポイントを表すデータをシリアル化し、エクスペリエンスで共有している他のデバイスに送信できます。 その後、各デバイスはアンカー データをシリアル化解除し、空間内のそのポイントの検索を試みます。 アンカー転送を機能させるには、アンカーによって表されるポイントを識別できるように、各デバイスが十分な環境でスキャンされている必要があります。

セットアップ

このページのサンプル コードには、初期化する必要があるいくつかのフィールドがあります。

  1. GameObject rootGameObject は、Unityの GameObject であり、その上に WorldAnchor コンポーネントがあります。 共有エクスペリエンスの 1 人のユーザーがこの GameObject を 配置し、他のユーザーにデータをエクスポートします。
  2. WorldAnchor gameRootAnchor は、rootGameObject 上にある UnityEngine.XR.WSA.WorldAnchor です。
  3. byte[] importedData は、各クライアントがネットワーク経由で受信しているシリアル化されたアンカーのバイト配列です。
public GameObject rootGameObject;
private UnityEngine.XR.WSA.WorldAnchor gameRootAnchor;

void Start ()
{
    gameRootAnchor = rootGameObject.GetComponent<UnityEngine.XR.WSA.WorldAnchor>();

    if (gameRootAnchor == null)
    {
        gameRootAnchor = rootGameObject.AddComponent<UnityEngine.XR.WSA.WorldAnchor>();
    }
}

エクスポート

エクスポートするには、 WorldAnchor が必要であり、受信アプリにとって意味を持つように、何と呼ばれるかを知る必要があります。 共有エクスペリエンスの 1 つのクライアントで、次の手順を実行して共有アンカーをエクスポートします。

  1. WorldAnchorTransferBatch を作成する
  2. 転送する WorldAnchors を追加する
  3. エクスポートを開始する
  4. データが使用可能になったとき に OnExportDataAvailable イベントを処理する
  5. OnExportComplete イベントを処理する

転送する内容をカプセル化し、それをバイトにエクスポートする WorldAnchorTransferBatch を作成します。

private void ExportGameRootAnchor()
{
    WorldAnchorTransferBatch transferBatch = new WorldAnchorTransferBatch();
    transferBatch.AddWorldAnchor("gameRoot", this.gameRootAnchor);
    WorldAnchorTransferBatch.ExportAsync(transferBatch, OnExportDataAvailable, OnExportComplete);
}

データが使用可能になったら、データのセグメントが使用可能になると、バイトをクライアントまたはバッファーに送信し、必要な手段を介して送信します。

private void OnExportDataAvailable(byte[] data)
{
    TransferDataToClient(data);
}

エクスポートが完了したら、データを転送していてシリアル化が失敗した場合は、データを破棄するようにクライアントに指示します。 シリアル化が成功した場合は、すべてのデータが転送され、インポートを開始できることをクライアントに伝えます。

private void OnExportComplete(SerializationCompletionReason completionReason)
{
    if (completionReason != SerializationCompletionReason.Succeeded)
    {
        SendExportFailedToClient();
    }
    else
    {
        SendExportSucceededToClient();
    }
}

輸入

送信者からすべてのバイトを受信した後、 データを WorldAnchorTransferBatch にインポートし、ルート ゲーム オブジェクトを同じ物理的な場所にロックできます。 注: インポートは一時的に失敗する場合があり、再試行する必要があります。

// This byte array should have been updated over the network from TransferDataToClient
private byte[] importedData;
private int retryCount = 3;

private void ImportRootGameObject()
{
    WorldAnchorTransferBatch.ImportAsync(importedData, OnImportComplete);
}

private void OnImportComplete(SerializationCompletionReason completionReason, WorldAnchorTransferBatch deserializedTransferBatch)
{
    if (completionReason != SerializationCompletionReason.Succeeded)
    {
        Debug.Log("Failed to import: " + completionReason.ToString());
        if (retryCount > 0)
        {
            retryCount--;
            WorldAnchorTransferBatch.ImportAsync(importedData, OnImportComplete);
        }
        return;
    }

    this.gameRootAnchor = deserializedTransferBatch.LockObject("gameRoot", this.rootGameObject);
}

LockObject 呼び出しによって GameObject がロックされた後、WorldAnchor はワールド内の同じ物理的な位置に保持されますが、Unity座標空間内の他のユーザーとは異なる場所にある可能性があります。