Trasferimenti di ancoraggi locali in Unity

Nei casi in cui non è possibile usare Ancoraggi nello spazio di Azure, i trasferimenti di ancoraggi locali consentono a un dispositivo HoloLens di esportare un ancoraggio da importare da un secondo dispositivo HoloLens.

Nota

I trasferimenti di ancoraggio locale offrono un richiamo di ancoraggio meno affidabile rispetto ad Ancoraggi nello spazio di Azure e i dispositivi iOS e Android non sono supportati da questo approccio.

Impostazione della funzionalità SpatialPerception

Per consentire a un'app di trasferire ancoraggi nello spazio, è necessario abilitare la funzionalità SpatialPerception .

Come abilitare la funzionalità SpatialPerception :

  1. Nell'editor di Unity aprire il riquadro "Impostazioni lettore" (Modifica > lettore impostazioni > progetto)
  2. Fare clic sulla scheda "Windows Store"
  3. Espandere "Impostazioni di pubblicazione" e controllare la funzionalità "SpatialPerception" nell'elenco "Funzionalità"

Nota

Se il progetto Unity è già stato esportato in una soluzione di Visual Studio, sarà necessario esportare in una nuova cartella o impostare manualmente questa funzionalità in AppxManifest in Visual Studio.

Trasferimento di ancoraggi

Namespace:UnityEngine.XR.WSA.Sharing
Tipo: WorldAnchorTransferBatch

Per trasferire un WorldAnchor, è necessario stabilire l'ancoraggio da trasferire. L'utente di un dispositivo HoloLens esegue l'analisi dell'ambiente e sceglie manualmente o a livello di codice un punto nello spazio per l'ancoraggio per l'esperienza condivisa. I dati che rappresentano questo punto possono quindi essere serializzati e trasmessi agli altri dispositivi che condividono nell'esperienza. Ogni dispositivo quindi de-serializza i dati di ancoraggio e tenta di individuare tale punto nello spazio. Per consentire il funzionamento del trasferimento dell'ancoraggio, ogni dispositivo deve essere stato analizzato in un ambiente sufficiente in modo che sia possibile identificare il punto rappresentato dall'ancoraggio.

Installazione

Il codice di esempio in questa pagina include alcuni campi che dovranno essere inizializzati:

  1. GameObject rootGameObject è un GameObject in Unity con un componente WorldAnchor . Un utente nell'esperienza condivisa inserisce questo GameObject ed esporta i dati negli altri utenti.
  2. WorldAnchor gameRootAnchor è UnityEngine.XR.WSA.WorldAnchor presente in rootGameObject.
  3. byte[] importedData è una matrice di byte per l'ancoraggio serializzato che ogni client riceve in rete.
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>();
    }
}

Esportazione

Per esportare, è sufficiente un WorldAnchor e sapere cosa lo chiameremo in modo che abbia senso per l'app ricevente. Un client nell'esperienza condivisa eseguirà questi passaggi per esportare l'ancoraggio condiviso:

  1. Creare un WorldAnchorTransferBatch
  2. Aggiungere WorldAnchors per il trasferimento
  3. Avviare l'esportazione
  4. Gestire l'evento OnExportDataAvailable man mano che i dati diventano disponibili
  5. Gestire l'evento OnExportComplete

Viene creato un WorldAnchorTransferBatch per incapsulare ciò che verrà trasferito e quindi esportarlo in byte:

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

Man mano che i dati diventano disponibili, inviare i byte al client o al buffer come segmenti di dati sono disponibili e inviare tramite qualsiasi mezzo desiderato:

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

Al termine dell'esportazione, se il trasferimento dei dati e la serializzazione non sono riusciti, indicare al client di rimuovere i dati. Se la serializzazione è riuscita, indicare al client che tutti i dati sono stati trasferiti e che l'importazione può iniziare:

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

Importazione

Dopo aver ricevuto tutti i byte dal mittente, è possibile importare nuovamente i dati in un WorldAnchorTransferBatch e bloccare l'oggetto gioco radice nella stessa posizione fisica. Nota: l'importazione a volte avrà esito negativo temporaneo e deve essere ritentata:

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

Dopo che un GameObject è bloccato tramite la chiamata a LockObject , avrà un WorldAnchor che lo manterrà nella stessa posizione fisica del mondo, ma potrebbe trovarsi in una posizione diversa nello spazio delle coordinate unity rispetto ad altri utenti.