Överföringar av lokala ankare i Unity

I situationer där du inte kan använda Azure Spatial Anchors gör lokala fästpunktsöverföringar att en HoloLens-enhet kan exportera en fästpunkt som ska importeras av en andra HoloLens-enhet.

Anteckning

Lokala fästpunktsöverföringar ger mindre robust fästpunktsåterkallelse än Azure Spatial Anchors, och iOS- och Android-enheter stöds inte av den här metoden.

Ställa in SpatialPerception-funktionen

För att en app ska kunna överföra spatiala fästpunkter måste spatialperception-funktionen vara aktiverad.

Så här aktiverar du SpatialPerception-funktionen :

  1. I Unity-redigeraren öppnar du fönstret "Spelarinställningar" (Redigera > projektinställningar > spelare)
  2. Klicka på fliken "Windows Store"
  3. Expandera "Publiceringsinställningar" och kontrollera funktionen "SpatialPerception" i listan "Funktioner"

Anteckning

Om du redan har exporterat Unity-projektet till en Visual Studio-lösning måste du antingen exportera till en ny mapp eller manuellt ange den här funktionen i AppxManifest i Visual Studio.

Fästpunktsöverföring

Namnområde:UnityEngine.XR.WSA.Sharing
Typ: WorldAnchorTransferBatch

För att överföra en WorldAnchor måste man upprätta ankaret som ska överföras. Användaren av en HoloLens genomsöker sin miljö och väljer antingen manuellt eller programmässigt en punkt i utrymmet som fästpunkt för den delade upplevelsen. De data som representerar den här punkten kan sedan serialiseras och överföras till de andra enheter som delar i upplevelsen. Varje enhet av-serialiserar sedan fästpunktsdata och försöker hitta den punkten i utrymmet. För att anchoröverföringen ska fungera måste varje enhet ha genomsökt tillräckligt i miljön så att den punkt som representeras av fästpunkten kan identifieras.

Installation

Exempelkoden på den här sidan innehåller några fält som måste initieras:

  1. GameObject rootGameObject är ett GameObject i Unity som har en WorldAnchor-komponent på sig. En användare i den delade upplevelsen placerar detta GameObject och exporterar data till de andra användarna.
  2. WorldAnchor gameRootAnchor är UnityEngine.XR.WSA.WorldAnchor som finns på rootGameObject.
  3. byte[] importedData är en bytematris för den serialiserade fästpunkt som varje klient tar emot över nätverket.
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>();
    }
}

Exporterande

För att exportera behöver vi bara en WorldAnchor och för att veta vad vi kallar den så att den passar för den mottagande appen. En klient i den delade upplevelsen utför dessa steg för att exportera den delade fästpunkten:

  1. Skapa en WorldAnchorTransferBatch
  2. Lägg till WorldAnchors som ska överföras
  3. Påbörja exporten
  4. Hantera händelsen OnExportDataAvailable när data blir tillgängliga
  5. Hantera OnExportComplete-händelsen

Vi skapar en WorldAnchorTransferBatch för att kapsla in det vi ska överföra och sedan exportera det till byte:

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

När data blir tillgängliga skickar du bytes till klienten eller bufferten när segment av data är tillgängliga och skickar igenom det sätt som önskas:

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

När exporten är klar, om vi har överfört data och serialiseringen misslyckades, ber du klienten att ta bort data. Om serialiseringen lyckades meddelar du klienten att alla data har överförts och att importen kan starta:

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

Import

När vi har tagit emot alla byte från avsändaren kan vi importera tillbaka data till en WorldAnchorTransferBatch och låsa rotspelsobjektet till samma fysiska plats. Obs! Importen misslyckas ibland tillfälligt och måste göras om:

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

När ett GameObject har låsts via LockObject-anropet har det en WorldAnchor som håller den i samma fysiska position i världen, men den kan finnas på en annan plats i Unity-koordinatutrymmet än andra användare.