Compartilhar via


Transferências de âncora local no Unity

As transferências de âncora local permitem que um dispositivo HoloLens exporte uma âncora a ser importada por um segundo dispositivo HoloLens.

Observação

Dispositivos iOS e Android não são suportados por essa abordagem.

Configurando a funcionalidade SpatialPerception

Para que um aplicativo transfira âncoras espaciais, a funcionalidade SpatialPerception deve ser habilitada.

Como habilitar o recurso SpatialPerception :

  1. No Editor do Unity, abra o painel "Configurações do Player" (Editar > Configurações > do Projeto do Player)
  2. Clique na guia "Windows Store"
  3. Expanda "Configurações de publicação" e marque o recurso "SpatialPerception" na lista "Recursos"

Observação

Se você já tiver exportado seu projeto do Unity para uma solução do Visual Studio, precisará exportar para uma nova pasta ou definir manualmente essa funcionalidade no AppxManifest no Visual Studio.

Transferência de âncora

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

Para transferir um WorldAnchor, é necessário estabelecer a âncora a ser transferida. O usuário de um HoloLens verifica seu ambiente e escolhe manual ou programaticamente um ponto no espaço para ser a âncora para a experiência compartilhada. Os dados que representam esse ponto podem ser serializados e transmitidos para os outros dispositivos que estão compartilhando a experiência. Em seguida, cada dispositivo desserializa os dados de âncora e tenta localizar esse ponto no espaço. Para que a Transferência de Âncora funcione, cada dispositivo deve ter verificado o suficiente do ambiente para que o ponto representado pela âncora possa ser identificado.

Instalação

O código de exemplo nesta página tem alguns campos que precisarão ser inicializados:

  1. GameObject rootGameObject é um GameObject no Unity que tem um componente WorldAnchor . Um usuário na experiência compartilhada colocará esse GameObject e exportará os dados para os outros usuários.
  2. WorldAnchor gameRootAnchor é o UnityEngine.XR.WSA.WorldAnchor que está em rootGameObject.
  3. byte[] importedData é uma matriz de bytes para a âncora serializada que cada cliente está recebendo pela rede.
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>();
    }
}

Exportação

Para exportar, precisamos apenas de um WorldAnchor e saber como vamos chamá-lo de forma que faça sentido para o aplicativo receptor. Um cliente na experiência compartilhada executará estas etapas para exportar a âncora compartilhada:

  1. Criar um WorldAnchorTransferBatch
  2. Adicione as WorldAnchors para transferir
  3. Iniciar a exportação
  4. Manipular o evento OnExportDataAvailable à medida que os dados se tornam disponíveis
  5. Manipular o evento OnExportComplete

Criamos um WorldAnchorTransferBatch para encapsular o que transferiremos e, em seguida, exportamos isso para bytes:

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

À medida que os dados se tornam disponíveis, envie os bytes para o cliente ou buffer à medida que os segmentos de dados estiverem disponíveis e envie por qualquer meio desejado:

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

Depois que a exportação for concluída, se estivermos transferindo dados e a serialização falhar, diga ao cliente para descartar os dados. Se a serialização for bem-sucedida, informe ao cliente que todos os dados foram transferidos e a importação pode começar:

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

Importação

Depois de receber todos os bytes do remetente, podemos importar os dados de volta para um WorldAnchorTransferBatch e bloquear nosso objeto de jogo raiz no mesmo local físico. Nota: a importação às vezes falhará transitoriamente e precisa ser repetida:

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

Depois que um GameObject for bloqueado por meio da chamada LockObject , ele terá um WorldAnchor que o manterá na mesma posição física no mundo, mas pode estar em um local diferente no espaço de coordenadas do Unity do que outros usuários.