Unity では、ローカルのアンカー転送Local anchor transfers in Unity

使用できない状況でAzure 空間アンカー、ローカルのアンカーの転送には、2 番目の HoloLens デバイスによってインポートされるアンカーをエクスポートする 1 つの HoloLens デバイスが有効にします。In situations where you cannot use Azure Spatial Anchors, local anchor transfers enable one HoloLens device to export an anchor to be imported by a second HoloLens device.

注意

ローカルのアンカー転送よりも堅牢性のアンカー再現率を提供するAzure 空間アンカー、iOS および Android デバイスは、このアプローチではサポートされていないとします。Local anchor transfers provide less robust anchor recall than Azure Spatial Anchors, and iOS and Android devices are not supported by this approach.

SpatialPerception 機能の設定Setting the SpatialPerception capability

空間のアンカーを転送するアプリのために、 SpatialPerception機能を有効にする必要があります。In order for an app to transfer spatial anchors, the SpatialPerception capability must be enabled.

有効にする方法、 SpatialPerception機能。How to enable the SpatialPerception capability:

  1. Unity エディターで開き、 「プレーヤー設定」 ウィンドウ (編集 > プロジェクトの設定 > Player)In the Unity Editor, open the "Player Settings" pane (Edit > Project Settings > Player)
  2. をクリックして、 "Windows Store" タブClick on the "Windows Store" tab
  3. 展開 「発行の設定」 を確認し、 "SpatialPerception" 機能、 「機能」 一覧Expand "Publishing Settings" and check the "SpatialPerception" capability in the "Capabilities" list

注意

Visual Studio ソリューションに既に Unity プロジェクトをエクスポートした場合は、新しいフォルダーをまたは手動でいずれかのエクスポートする必要があります。 Visual Studio で AppxManifest でこの機能を設定します。If you have already exported your Unity project to a Visual Studio solution, you will need to either export to a new folder or manually set this capability in the AppxManifest in Visual Studio.

アンカーの転送Anchor Transfer

名前空間: UnityEngine.XR.WSA.SharingNamespace: UnityEngine.XR.WSA.Sharing
種類:WorldAnchorTransferBatchType: WorldAnchorTransferBatch

転送する、 WorldAnchor、1 つの送信をアンカーを確立する必要があります。To transfer a WorldAnchor, one must establish the anchor to be transferred. HoloLens の 1 つのユーザーは各自の環境をスキャンし、手動またはプログラムでは、領域を共有のエクスペリエンスのアンカーでポイントを選択します。The user of one HoloLens scans their environment and either manually or programmatically chooses a point in space to be the Anchor for the shared experience. この点を表すデータをシリアル化、およびエクスペリエンスで共有している他のデバイスに送信します。The data that represents this point can then be serialized and transmitted to the other devices that are sharing in the experience. 各デバイスに、アンカーのデータをシリアル化解除し、領域内でそのポイントを検索しようとしています。Each device then de-serializes the anchor data and attempts to locate that point in space. 作業にアンカーを転送するためは、アンカーによって表されるポイントを識別できるように、環境を十分に各デバイスをスキャンしてする必要があります。In order for Anchor Transfer to work, each device must have scanned in enough of the environment such that the point represented by the anchor can be identified.

セットアップSetup

このページのサンプル コードでは、初期化する必要のあるいくつかのフィールドがあります。The sample code on this page has a few fields that will need to be initialized:

  1. GameObject rootGameObjectは、 GameObjectが Unity で、 WorldAnchorのコンポーネント。GameObject rootGameObject is a GameObject in Unity that has a WorldAnchor Component on it. 共有のエクスペリエンスの 1 人のユーザーには、この配置はGameObjectおよびその他のユーザーにデータをエクスポートします。One user in the shared experience will place this GameObject and export the data to the other users.
  2. WorldAnchor gameRootAnchorは、 UnityEngine.XR.WSA.WorldAnchorですrootGameObjectします。WorldAnchor gameRootAnchor is the UnityEngine.XR.WSA.WorldAnchor that is on rootGameObject.
  3. バイト [importedDataは各クライアントがネットワーク経由で受け取るシリアル化されたアンカーのバイト配列です。byte[] importedData is a byte array for the serialized anchor each client is receiving over the network.
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>();
    }
}

エクスポートします。Exporting

エクスポートするだけ、 WorldAnchorはいわゆるがある場合、受信側のアプリを把握するとします。To export, we just need a WorldAnchor and to know what we will call it such that it makes sense for the receiving app. 共有のエクスペリエンスで 1 つのクライアントでは、共有のアンカーをエクスポートするこれらの手順を実行します。One client in the shared experience will perform these steps to export the shared anchor:

  1. 作成、 WorldAnchorTransferBatchCreate a WorldAnchorTransferBatch
  2. 追加、 WorldAnchorsを転送するにはAdd the WorldAnchors to transfer
  3. エクスポートを開始します。Begin the export
  4. 処理、 OnExportDataAvailableデータとしてイベントが使用可能になりますHandle the OnExportDataAvailable event as data becomes available
  5. 処理、 OnExportCompleteイベントHandle the OnExportComplete event

作成、 WorldAnchorTransferBatch何をカプセル化するには、転送してバイトにエクスポートしは。We create a WorldAnchorTransferBatch to encapsulate what we will be transferring and then export that into bytes:

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

データが使用可能なデータのセグメントが使用可能で、クライアントまたはバッファーにバイトを送信し、必要な手段を通じて送信。As data becomes available, send the bytes to the client or buffer as segments of data is available and send through whatever means desired:

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

エクスポートが完了すると、転送されてデータとシリアル化が失敗した場合は、データを破棄するクライアントに指示します。Once the export is complete, if we have been transferring data and serialization failed, tell the client to discard the data. シリアル化に成功した場合をクライアントに指示するすべてのデータが転送され、インポートを開始できます。If the serialization succeeded, tell the client that all data has been transferred and importing can start:

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

インポートします。Importing

すべてのバイトを受信、送信側から後、にデータをインポートできます、 WorldAnchorTransferBatchと物理的に同じ場所に、ルートのゲーム オブジェクトをロックします。After receiving all of the bytes from the sender, we can import the data back into a WorldAnchorTransferBatch and lock our root game object into the same physical location. 注: インポートは一時的に場合によっては失敗し、再試行する必要があります。Note: import will sometimes transiently fail and needs to be retried:

// 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);
}

後に、 GameObject経由でロックされている、 LockObjectの呼び出しをWorldAnchorする世界では、同じ物理的な位置に維持されますが、可能性がある、Unity で別の場所は、他のユーザーよりも容量を調整します。After a GameObject is locked via the LockObject call, it will have a WorldAnchor which will keep it in the same physical position in the world, but it may be at a different location in the Unity coordinate space than other users.