Trasferimenti di ancoraggi locali in Unity
In situazioni 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 ancoraggi locali forniscono 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 :
- Nell'editor di Unity aprire il riquadro "Impostazioni lettore" (Modifica > lettore impostazioni > progetto)
- Fare clic sulla scheda "Windows Store"
- 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 ancoraggio
Spazio dei nomi: UnityEngine.XR.WSA.Sharing
Tipo: WorldAnchorTransferBatch
Per trasferire un WorldAnchor, è necessario stabilire l'ancoraggio da trasferire. L'utente di un dispositivo HoloLens analizza l'ambiente e sceglie manualmente o a livello di codice un punto nello spazio in modo che sia 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 di ancoraggio, ogni dispositivo deve aver eseguito l'analisi in un ambiente sufficiente in modo che sia possibile identificare il punto rappresentato dall'ancoraggio.
Attrezzaggio
Il codice di esempio in questa pagina include alcuni campi che dovranno essere inizializzati:
- 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.
- WorldAnchor gameRootAnchor è UnityEngine.XR.WSA.WorldAnchor che si trova in rootGameObject.
- 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:
- Creare un WorldAnchorTransferBatch
- Aggiungere WorldAnchors per il trasferimento
- Avviare l'esportazione
- Gestire l'evento OnExportDataAvailable man mano che i dati diventano disponibili
- 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 disponibili e inviarli 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 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.