Share via


Lokale ankeroverdrachten in Unity

In situaties waarin u Azure Spatial Anchors niet kunt gebruiken, kunnen lokale ankeroverdrachten één HoloLens-apparaat inschakelen om een anker te exporteren dat moet worden geïmporteerd door een tweede HoloLens-apparaat.

Notitie

Lokale ankeroverdrachten bieden minder robuuste ankerherroep dan Azure Spatial Anchors, en iOS- en Android-apparaten worden niet ondersteund door deze aanpak.

De mogelijkheid SpatialPerception instellen

Als u wilt dat een app ruimtelijke ankers overbrengt, moet de mogelijkheid SpatialPerception zijn ingeschakeld.

De mogelijkheid SpatialPerception inschakelen:

  1. Open in de Unity-editor het deelvenster 'Spelerinstellingen' (Projectinstellingen > bewerken > Speler)
  2. Klik op het tabblad Windows Store
  3. Vouw 'Publicatie-instellingen' uit en controleer de mogelijkheid 'SpatialPerception' in de lijst 'Mogelijkheden'

Notitie

Als u uw Unity-project al hebt geëxporteerd naar een Visual Studio-oplossing, moet u exporteren naar een nieuwe map of deze mogelijkheid handmatig instellen in appxManifest in Visual Studio.

Ankeroverdracht

Naamruimte:UnityEngine.XR.WSA.Sharing
Type: WorldAnchorTransferBatch

Om een WorldAnchor over te dragen, moet men het anker instellen dat moet worden overgedragen. De gebruiker van een HoloLens scant zijn omgeving en kiest handmatig of programmatisch een punt in de ruimte als anker voor de gedeelde ervaring. De gegevens die dit punt vertegenwoordigen, kunnen vervolgens worden geserialiseerd en verzonden naar de andere apparaten die in de ervaring delen. Elk apparaat verwijdert vervolgens de serialisatie van de ankergegevens en probeert dat punt in de ruimte te vinden. Ankeroverdracht werkt alleen als elk apparaat voldoende van de omgeving heeft gescand, zodat het punt dat door het anker wordt vertegenwoordigd, kan worden geïdentificeerd.

Instellen

De voorbeeldcode op deze pagina bevat enkele velden die moeten worden geïnitialiseerd:

  1. GameObject rootGameObject is een GameObject in Unity met een WorldAnchor-onderdeel . Eén gebruiker in de gedeelde ervaring plaatst dit GameObject en exporteert de gegevens naar de andere gebruikers.
  2. WorldAnchor gameRootAnchor is de UnityEngine.XR.WSA.WorldAnchor die zich op rootGameObject bevindt.
  3. byte[] importedData is een bytematrix voor het geserialiseerde anker dat elke client via het netwerk ontvangt.
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>();
    }
}

Exporteren

Om te exporteren, hebben we alleen een WorldAnchor nodig en om te weten hoe we het zo zullen noemen dat het zinvol is voor de ontvangende app. Eén client in de gedeelde ervaring voert deze stappen uit om het gedeelde anker te exporteren:

  1. Een WorldAnchorTransferBatch maken
  2. De WorldAnchors toevoegen om over te dragen
  3. De export starten
  4. De gebeurtenis OnExportDataAvailable verwerken wanneer er gegevens beschikbaar komen
  5. De gebeurtenis OnExportComplete afhandelen

We maken een WorldAnchorTransferBatch om in te kapselen wat we gaan overdragen en exporteren dat vervolgens in bytes:

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

Zodra gegevens beschikbaar zijn, verzendt u de bytes naar de client of buffer zodra er gegevenssegmenten beschikbaar zijn en verzendt u op de gewenste wijze:

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

Zodra de export is voltooid en we gegevens hebben overgedragen en de serialisatie is mislukt, vertelt u de client dat de gegevens moeten worden verwijderd. Als de serialisatie is geslaagd, vertelt u de client dat alle gegevens zijn overgedragen en dat het importeren kan worden gestart:

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

Importeren

Nadat we alle bytes van de afzender hebben ontvangen, kunnen we de gegevens weer importeren in een WorldAnchorTransferBatch en ons hoofdspelobject op dezelfde fysieke locatie vergrendelen. Opmerking: importeren mislukt soms tijdelijk en moet opnieuw worden geprobeerd:

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

Nadat een GameObject is vergrendeld via de Aanroep LockObject , heeft deze een WorldAnchor die het in dezelfde fysieke positie in de wereld houdt, maar het kan zich op een andere locatie in de Unity-coördinaatruimte bevinden dan andere gebruikers.