Lokale Anker Übertragungen in UnityLocal anchor transfers in Unity

In Fällen, in denen Sie keine räumlichen Anker von Azureverwenden können, ermöglichen lokale Anker Übertragungen einem hololens-Gerät das Exportieren eines Ankers, der von einem zweiten hololens-Gerät importiert werden soll.In situations where you cannot use Azure Spatial Anchors, local anchor transfers enable one HoloLens device to export an anchor to be imported by a second HoloLens device.

Hinweis

Lokale Anker Übertragungen bieten weniger robusten Anker als Anker als räumliche Azure-Anker, und IOS-und Android-Geräte werden von diesem Ansatz nicht unterstützt.Local anchor transfers provide less robust anchor recall than Azure Spatial Anchors, and iOS and Android devices are not supported by this approach.

Festlegen der spatialperception-FunktionSetting the SpatialPerception capability

Damit eine APP räumliche Anker übertragen kann, muss die spatialperception -Funktion aktiviert werden.In order for an app to transfer spatial anchors, the SpatialPerception capability must be enabled.

Aktivieren der spatialperception -Funktion:How to enable the SpatialPerception capability:

  1. Öffnen Sie im Unity-Editor den Bereich "Player Einstellungen" (Bearbeiten > Projekteinstellungen > Player).In the Unity Editor, open the "Player Settings" pane (Edit > Project Settings > Player)
  2. Klicken Sie auf die Registerkarte "Windows Store" .Click on the "Windows Store" tab
  3. Erweitern Sie "Veröffentlichungs Einstellungen" , und überprüfen Sie die Funktion "spatialperception" in der Liste "Funktionen" .Expand "Publishing Settings" and check the "SpatialPerception" capability in the "Capabilities" list

Hinweis

Wenn Sie Ihr Unity-Projekt bereits in eine Visual Studio-Projekt Mappe exportiert haben, müssen Sie entweder in einen neuen Ordner exportieren oder Diese Funktion manuell in "appxmanifest" in Visual Studio festlegen.If you have already exported your Unity project to a Visual Studio solution, you will need to either export to a new folder or manually set this capability in the AppxManifest in Visual Studio.

Anker ÜbertragungAnchor Transfer

Namespace: unityengine. XR. WSA. SharingNamespace: UnityEngine.XR.WSA.Sharing
Typ: worldanchortransferbatchType: WorldAnchorTransferBatch

Zum Übertragen eines worldanchorsmüssen Sie den Anker einrichten, der übertragen werden soll.To transfer a WorldAnchor, one must establish the anchor to be transferred. Der Benutzer eines hololens scannt seine Umgebung und wählt entweder manuell oder Programm gesteuert einen Punkt im Bereich aus, um als Anker für die gemeinsame Nutzung zu gelten.The user of one HoloLens scans their environment and either manually or programmatically chooses a point in space to be the Anchor for the shared experience. Die Daten, die diesen Punkt darstellen, können dann serialisiert und an die anderen Geräte übertragen werden, die in der-Funktion gemeinsam genutzt werden.The data that represents this point can then be serialized and transmitted to the other devices that are sharing in the experience. Jedes Gerät deserialisiert dann die Anker Daten und versucht, diesen Punkt im Speicherplatz zu finden.Each device then de-serializes the anchor data and attempts to locate that point in space. Damit die Anker Übertragung funktioniert, muss jedes Gerät in genügend der Umgebung gescannt werden, damit der durch den Anker dargestellte Punkt identifiziert werden kann.In order for Anchor Transfer to work, each device must have scanned in enough of the environment such that the point represented by the anchor can be identified.

EinrichtenSetup

Der Beispielcode auf dieser Seite verfügt über einige Felder, die initialisiert werden müssen:The sample code on this page has a few fields that will need to be initialized:

  1. Gameobject rootgameobject ist ein gameobject in Unity, das über eine worldanchor -Komponente verfügt.GameObject rootGameObject is a GameObject in Unity that has a WorldAnchor Component on it. Ein Benutzer in der freigegebenen Benutzer Darstellung wird dieses gameobject platzieren und die Daten an die anderen Benutzer exportieren.One user in the shared experience will place this GameObject and export the data to the other users.
  2. Worldanchor gamerootanchor ist das unityengine. XR. WSA. worldanchor -Objekt, das auf rootgameobject basiert.WorldAnchor gameRootAnchor is the UnityEngine.XR.WSA.WorldAnchor that is on rootGameObject.
  3. Byte [] importeddata ist ein Bytearray für den serialisierten Anker, der von jedem Client über das Netzwerk empfangen wird.byte[] importedData is a byte array for the serialized anchor each client is receiving over the network.
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>();
    }
}

ExportExporting

Zum Exportieren benötigen wir lediglich einen worldanchor und wissen, wie wir ihn nennen werden, damit er für die empfangende App sinnvoll ist.To export, we just need a WorldAnchor and to know what we will call it such that it makes sense for the receiving app. Ein Client in der freigegebenen Darstellung führt diese Schritte aus, um den gemeinsamen Anker zu exportieren:One client in the shared experience will perform these steps to export the shared anchor:

  1. Erstellen eines worldanchortransferbatchesCreate a WorldAnchorTransferBatch
  2. Zu übertragenden worldanchors hinzufügenAdd the WorldAnchors to transfer
  3. Export startenBegin the export
  4. Behandeln Sie das onexportdataavailable -Ereignis, wenn Daten verfügbar werden.Handle the OnExportDataAvailable event as data becomes available
  5. Behandeln des onexportcomplete -EreignissesHandle the OnExportComplete event

Wir erstellen einen worldanchortransferbatch , um zu kapseln, was wir übertragen werden, und exportieren Sie dann in Bytes:We create a WorldAnchorTransferBatch to encapsulate what we will be transferring and then export that into bytes:

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

Wenn Daten verfügbar werden, senden Sie die Bytes an den Client oder Puffer, wenn Daten Segmente verfügbar sind, und senden Sie Sie über beliebige Möglichkeiten:As data becomes available, send the bytes to the client or buffer as segments of data is available and send through whatever means desired:

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

Nachdem der Export abgeschlossen ist, weisen Sie den Client an, die Daten zu verwerfen, wenn die Daten übertragen wurden und die Serialisierung fehlgeschlagen ist.Once the export is complete, if we have been transferring data and serialization failed, tell the client to discard the data. Wenn die Serialisierung erfolgreich war, teilen Sie dem Client mit, dass alle Daten übertragen wurden und der Import Vorgang gestartet werden kann:If the serialization succeeded, tell the client that all data has been transferred and importing can start:

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

ImportierenImporting

Nachdem alle Bytes vom Absender empfangen wurden, können wir die Daten zurück in ein worldanchortransferbatch importieren und das Stamm Spielobjekt an demselben physischen Speicherort sperren.After receiving all of the bytes from the sender, we can import the data back into a WorldAnchorTransferBatch and lock our root game object into the same physical location. Hinweis: der Import schlägt gelegentlich fehl, und es muss ein erneuter Versuch unternommen werden:Note: import will sometimes transiently fail and needs to be retried:

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

Nachdem ein gameobject-Objekt über den Lock Object -Befehl gesperrt wurde, verfügt es über einen worldanchor , der ihn an derselben physischen Position in der Welt hält, er kann sich aber an einem anderen Speicherort im Unity-Koordinaten Bereich befinden als andere Benutzer.After a GameObject is locked via the LockObject call, it will have a WorldAnchor which will keep it in the same physical position in the world, but it may be at a different location in the Unity coordinate space than other users.