Compartir a través de


Transferencias de anclaje local en Unity

En situaciones en las que no se puede usar Azure Spatial Anchors, las transferencias de delimitadores locales permiten que un dispositivo HoloLens exporte un delimitador para que lo importe un segundo dispositivo HoloLens.

Nota:

Las transferencias de delimitadores locales proporcionan una recuperación de anclaje menos sólida que Azure Spatial Anchors y los dispositivos iOS y Android no son compatibles con este enfoque.

Establecimiento de la funcionalidad SpatialPerception

Para que una aplicación transfiera anclajes espaciales, se debe habilitar la funcionalidad SpatialPerception .

Cómo habilitar la funcionalidad SpatialPerception :

  1. En el Editor de Unity, abra el panel "Configuración del reproductor" (Editar > reproductor de configuración del > proyecto)
  2. Haga clic en la pestaña "Tienda Windows"
  3. Expanda "Configuración de publicación" y compruebe la funcionalidad "SpatialPerception" en la lista "Capabilities" (Funcionalidades).

Nota:

Si ya ha exportado el proyecto de Unity a una solución de Visual Studio, deberá exportar a una nueva carpeta o establecer manualmente esta funcionalidad en AppxManifest en Visual Studio.

Transferencia de anclaje

Espacio de nombres: UnityEngine.XR.WSA.Sharing
Tipo: WorldAnchorTransferBatch

Para transferir un WorldAnchor, uno debe establecer el anclaje que se va a transferir. El usuario de un HoloLens examina su entorno y elige manualmente o mediante programación un punto en el espacio para ser el delimitador de la experiencia compartida. Los datos que representan este punto se pueden serializar y transmitir a los demás dispositivos que comparten la experiencia. A continuación, cada dispositivo des serializa los datos de delimitador e intenta localizar ese punto en el espacio. Para que la transferencia de anclaje funcione, cada dispositivo debe haber examinado lo suficiente en el entorno para que se pueda identificar el punto representado por el delimitador.

Configurar

El código de ejemplo de esta página tiene algunos campos que deberán inicializarse:

  1. GameObject rootGameObject es un GameObject en Unity que tiene un componente WorldAnchor en él. Un usuario de la experiencia compartida colocará este GameObject y exportará los datos a los demás usuarios.
  2. WorldAnchor gameRootAnchor es UnityEngine.XR.WSA.WorldAnchor que está en rootGameObject.
  3. byte[] importedData es una matriz de bytes para el delimitador serializado que cada cliente recibe a través de la red.
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>();
    }
}

Exportación

Para exportar, solo necesitamos un WorldAnchor y saber lo que llamaremos de modo que tenga sentido para la aplicación receptora. Un cliente de la experiencia compartida realizará estos pasos para exportar el delimitador compartido:

  1. Crear un WorldAnchorTransferBatch
  2. Agregar WorldAnchors para transferir
  3. Inicio de la exportación
  4. Controlar el evento OnExportDataAvailable a medida que los datos están disponibles
  5. Controlar el evento OnExportComplete

Creamos un WorldAnchorTransferBatch para encapsular lo que se va a transferir y luego exportarlo a bytes:

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

A medida que los datos están disponibles, envíe los bytes al cliente o al búfer a medida que haya segmentos de datos disponibles y envíe a través de los medios que desee:

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

Una vez completada la exportación, si se han producido errores en la transferencia de datos y serialización, indique al cliente que descarte los datos. Si la serialización se ha realizado correctamente, indique al cliente que todos los datos se han transferido e importen pueden iniciarse:

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

Importación

Después de recibir todos los bytes del remitente, podemos volver a importar los datos en un WorldAnchorTransferBatch y bloquear nuestro objeto de juego raíz en la misma ubicación física. Nota: La importación a veces producirá un error transitorio y debe reintentarse:

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

Después de bloquear un GameObject a través de la llamada LockObject, tendrá un WorldAnchor que lo mantendrá en la misma posición física del mundo, pero puede estar en una ubicación diferente en el espacio de coordenadas de Unity que otros usuarios.