Lokala fästpunktsöverföringar 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.
Kommentar
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.
Ange 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 :
- I Unity-redigeraren öppnar du fönstret "Spelarinställningar" (Redigera > projektinställningar > spelare)
- Klicka på fliken "Windows Store"
- Expandera "Publiceringsinställningar" och kontrollera funktionen "SpatialPerception" i listan "Funktioner"
Kommentar
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 fästpunkten som ska överföras. Användaren av en HoloLens söker igenom sin miljö och väljer antingen manuellt eller programmatiskt 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 fästpunktsö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.
Ställ in
Exempelkoden på den här sidan har några fält som måste initieras:
- GameObject rootGameObject är ett GameObject i Unity som har en WorldAnchor-komponent på sig. En användare i den delade upplevelsen placerar denna GameObject och exporterar data till de andra användarna.
- WorldAnchor gameRootAnchor är UnityEngine.XR.WSA.WorldAnchor som finns på rootGameObject.
- 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 det så att det är meningsfullt för den mottagande appen. En klient i den delade upplevelsen utför dessa steg för att exportera den delade fästpunkten:
- Skapa en WorldAnchorTransferBatch
- Lägg till WorldAnchors för överföring
- Påbörja exporten
- Hantera händelsen OnExportDataAvailable när data blir tillgängliga
- Hantera händelsen OnExportComplete
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 byteen till klienten eller bufferten eftersom segment av data är tillgängliga och skickar genom vilket medel som helst:
private void OnExportDataAvailable(byte[] data)
{
TransferDataToClient(data);
}
När exporten är klar, om vi har överfört data och serialiseringen misslyckades, uppmanar 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 på 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 en GameObject har låsts via LockObject-anropet har den 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.