Android XR

Como arquitetar conteúdo espacial no Android XR com o Unity

Alto-falantes

  • Levana Chen

    Engenheiro de software

  • Jennifer Stanton

    Engenheiro de software sênior

Sobre

Sobre a palestra

Descubra como fixar e manter experiências em 3D no mundo real usando o Unity e o Android XR. Esta sessão aborda o framework de entidades espaciais, as Cloud Anchors e as APIs Geospatial, demonstrando como criar apps que reconhecem o contexto, lembram posicionamentos físicos e sincronizam dados espaciais multiusuário entre sessões.

Vamos analisar a arquitetura por trás das entidades espaciais e entender como ancorar ativos digitais a objetos físicos, superfícies e localizações geográficas. Você vai aprender fluxos de trabalho práticos do Unity para mapear espaços, manter conteúdo em várias sessões e criar experiências de RA/XR compartilhadas e com reconhecimento de local.

Resumo

  • A AR Foundation oferece uma API de script unificada em plataformas XR usando extensões do OpenXR. Ele permite representar e consultar recursos do mundo real, como planos e malhas.
  • As âncoras persistentes estabilizam o conteúdo digital em várias sessões e reinicializações do dispositivo. É possível persistir com TrySaveAnchorAsync e recarregá-los usando GUIDs serializados.
  • O framework de entidades espaciais substitui as extensões rastreáveis para oferecer suporte multiplataforma e melhor desempenho no rastreamento de itens como caixas delimitadoras e marcadores.
  • Os componentes do gerenciador precisam ser desativados até que as permissões do Android XR sejam concedidas. Isso evita falhas de inicialização do subsistema causadas pelo acesso restrito a dados sensíveis do ambiente.
  • A API Geospatial usa os serviços do ARCore do Google Cloud e o VPS para posicionar conteúdo em locais reais ao ar livre.

Recursos

Gemini Notebook

Tópicos

  • android-xr
  • união
  • ar-foundation
  • openxr
  • spatial-entities
  • anúncios fixos
  • geospatial-api

Transcrição

Introdução e visão geral do AR Foundation

  • Certo.

  • Olá, pessoal!

  • Este é o curso "Como arquitetar conteúdo espacial no Android XR com o Unity".

  • Meu nome é Jennifer Stanton.

  • Trabalho na Unity como engenheiro de software sênior.

  • Trabalho na equipe de recursos de XR, especificamente na AR Foundation e nos pacotes relacionados que levam a realidade aumentada e mista ao Unity.

  • Sou Levana Chen, da equipe de mecanismos de jogos XR do Google.

  • Nossas equipes se concentraram em fornecer plug-ins e pacotes que oferecem funcionalidade de XR aprimorada e integrações perfeitas com mecanismos de jogo.

  • Um dos maiores desafios que vocês nos relatam é que oferecer suporte a várias plataformas de XR com a mesma base de código dá muito trabalho.

  • O AR Foundation é a camada de API de realidade estendida de alto nível do Unity.

  • Você pode segmentar várias plataformas de XR sem grandes reescritas de código, sem precisar gerenciar várias bases de código, e tem uma API de script para recursos de RA em qualquer plataforma.

  • Assim, você pode se concentrar em criar seu app, jogo ou experiência, e o Unity cuida dos detalhes da plataforma para você.

  • Uma maneira de fazer isso é com as extensões do OpenXR.

  • Elas são um conjunto de APIs abertas e padrão do setor definidas pelo Khronos Group.

  • O OpenXR também criou entidades espaciais.

  • É um framework para que o conteúdo digital represente e interaja com o mundo físico.

  • As entidades espaciais fornecem um modelo unificado para representar elementos do mundo real como objetos digitais.

  • É um prazer compartilhar com você algumas das informações mais recentes sobre a AR Foundation para que você possa começar sua jornada para criar experiências para XR.

  • Em seguida, vou falar sobre os recursos do AR Foundation para que seu conteúdo digital possa interagir com o mundo real.

  • Em seguida, vou falar sobre a configuração do projeto, incluindo pacotes e outras dependências, para que você possa implementar isso nos seus projetos.

  • Por fim, vou falar sobre alguns recursos exclusivos do Android XR.

Principais recursos do AR Foundation

  • Algumas das maneiras como a AR Foundation representa o mundo real digitalmente são os planos.

  • São superfícies planas no ambiente físico, como pisos, paredes, tetos e até mesas e sofás.

  • As malhas são estruturas 3D que representam a geometria do mundo físico.

  • E também temos formas de interagir com o mundo real, os raycasts.

  • Eles determinam onde um raio se cruza com o conteúdo digital.

  • Pense nele como um apontador laser, e você recebe informações sobre onde ele está apontando.

  • Também temos âncoras, que ajudam a estabilizar e realocar um ponto no espaço.

  • Vou falar mais sobre as âncoras mais adiante nesta apresentação.

  • Portanto, todos esses quatro são considerados recursos do AR Foundation.

  • Há também alguns outros recursos que não são mencionados neste slide.

  • Planos e âncoras, especificamente, são considerados rastreáveis porque estendem a classe ARTrackable, e os gerenciadores deles rastreiam atualizações do ambiente de execução.

  • Vamos falar sobre planos.

  • Planes, temos o componente ARPlane, que identifica superfícies planas em tempo real.

  • Eles têm rótulos semânticos que você pode consultar para saber se o plano é um chão, uma mesa, uma parede etc.

  • Os planos também têm limites dinâmicos. Assim, conforme o usuário se move pelo mundo real e consegue ver mais superfícies, os limites do plano se expandem, se fundem e se refinam em tempo real.

  • Também podemos anexar um colisor de malha ao plano para lidar com a física.

  • Aqui você pode ver um exemplo de detecção de plano.

  • Esta é a cena de raycast dos exemplos do AR Foundation em execução em um dispositivo Android XR.

  • Ele detecta polígonos 2D dinâmicos em tempo real.

  • Para criar um app com essa funcionalidade, siga nosso guia de configuração do projeto ou use um dos nossos exemplos ou modelos.

  • Em seguida, temos as malhas.

  • As malhas são um recurso de RA que fornece malhas 3D do ambiente.

  • Podemos anexar um colisor de malha a essas malhas geradas, o que permite que seu conteúdo digital interaja com objetos do mundo real.

  • As malhas permitem uma oclusão de objetos convincente.

  • Assim, um objeto virtual pode parecer estar atrás de um objeto físico.

  • Se o objeto digital puder se mover no espaço, use a mesma geometria para encontrar um caminho que evite objetos do mundo real.

  • Em seguida, temos o ray casting.

  • O ray casting projeta raios virtuais na sua cena 3D para procurar interseções sem que você precise se preocupar com cálculos matemáticos complexos.

  • O raio projetado pode cruzar vários objetos 3D no ambiente.

  • É possível configurar o raycast para atingir apenas determinados tipos de conteúdo digital.

  • Por exemplo, é possível configurá-lo para não atingir planos e apenas cruzar com malhas.

Configuração de pacotes e dependências

  • Agora, vamos analisar os pacotes relevantes.

  • Todos esses pacotes funcionam juntos para se comunicar e criar uma experiência de XR completa.

  • Como mencionado, o AR Foundation lida com recursos como planos e âncoras.

  • O plug-in do OpenXR processa APIs nativas em várias plataformas de XR. Portanto, use esse pacote se o dispositivo usar o OpenXR.

  • O plug-in do OpenXR pode ser pareado com o pacote de entidades espaciais do OpenXR para acessar extensões de entidades espaciais especificamente, e vamos falar mais sobre isso depois.

  • Se você sabe que vai segmentar especificamente dispositivos Android XR, como headsets XR e óculos XR com fio, o pacote Unity OpenXR Android XR é necessário.

  • Como tudo isso segue o padrão de plug-in, o impacto no seu código deve ser mínimo.

  • Nem todos os recursos estão disponíveis em todos os pacotes do AR Foundation.

  • Por exemplo, se você olhar para este gráfico, a malha não está disponível no pacote de entidades espaciais do Unity OpenXR.

  • O XR Plug-in Management permite gerenciar quais recursos do OpenXR estão selecionados no seu projeto.

  • No editor do Unity, acesse "Edit", "Configurações do Projeto" e, na barra lateral esquerda, "XR Plug-in Management".

  • Aqui você encontra os recursos e grupos de recursos do OpenXR, para selecionar e desmarcar os que quer incluir no build.

  • Por exemplo, nesta captura de tela, estamos vendo todas as que vêm com o pacote OpenXR do Android XR.

  • E você pode misturar e combinar essas entidades com as espaciais, por exemplo, se quiser.

  • Esta é a janela do Gerenciador de Pacotes.

  • Destaquei alguns dos pacotes que você pode encontrar em uma configuração típica de projeto de XR.

  • Como você pode ver, temos o AR Foundation, que já foi mencionado.

  • Também temos o plug-in do OpenXR.

  • Temos o pacote do Android XR.

  • Também destaquei algumas de outras plataformas, porque é possível criar um projeto que seja compilado para várias plataformas.

  • No canto inferior direito, também temos outros pacotes.

  • Composition Layers, que funcionam com dispositivos OpenXR; Core Utils, muito útil para tudo relacionado a XR; e XR Hands e XR Interaction Toolkit para receber sua entrada, o que é essencial.

  • Em seguida, temos a validação do projeto.

  • Isso faz parte do gerenciamento de plug-ins de XR.

  • A validação do projeto pode detectar recursos duplicados, além de outros problemas que precisam ser corrigidos para que o projeto seja executado.

  • Mas nesta captura de tela, destaquei os recursos duplicados.

  • Isso significa que dois dos mesmos recursos, como âncoras, planos e raycasts,

  • O usuário selecionou incluir duplicatas desses recursos de vários pacotes, e o sistema está apenas solicitando que ele selecione um ou outro.

Âncoras locais e persistência

  • Isso nos leva às âncoras locais e à persistência.

  • As âncoras garantem que o conteúdo digital permaneça nos locais desejados no ambiente, independentemente de mudanças no estado de rastreamento da sessão de RA.

  • As plataformas de RA atualizam automaticamente as posições das âncoras ao longo do tempo para garantir que elas permaneçam em uma posição consistente. As âncoras são a melhor maneira de garantir que o conteúdo permaneça no lugar se você se afastar e depois voltar para perto dela.

  • E se o usuário fechar o app, reiniciar mais tarde e voltar em uma sessão separada?

  • As âncoras persistentes permitem salvar âncoras em uma sessão de RA e carregá-las em sessões subsequentes.

  • Eles sobrevivem aos ciclos de vida do app e às reinicializações do dispositivo.

  • Aqui está um exemplo de âncoras persistentes no projeto AR Foundation Samples.

  • A cena de exemplo tem um menu com todas as funcionalidades compatíveis com essa plataforma, como salvar e carregar âncoras.

  • Isso nos leva ao ciclo de vida das âncoras persistentes.

  • Primeiro, você cria uma âncora localmente, que não é salva em nenhum lugar, nem mesmo no armazenamento permanente. É apenas uma âncora local.

  • Depois, você os persistiria no armazenamento.

  • Depois disso, você pode reiniciar o app e carregá-lo do armazenamento.

  • Algumas plataformas, incluindo o Android XR, também permitem apagar ou remover a persistência de âncoras.

  • O provedor de entidades espaciais permite carregar automaticamente todas as âncoras salvas para que você não precise solicitar manualmente cada âncora pelo ID.

  • Nas configurações do XR Plug-in Management, você pode selecionar a opção "Automatically Load Saved Anchors" no recurso "Spatial Entities: Anchors".

  • E salvar uma âncora requer apenas algumas linhas de código.

  • Primeiro, começamos no editor do Unity e verificamos se a cena está pronta adicionando o componente AR Anchor Manager ao objeto de jogo XR Origin.

  • O gerenciador mantém a cena atualizada com âncoras rastreadas do ambiente de execução.

  • Agora, vamos ao código.

  • Para adicionar uma âncora, basta chamar TryAddAnchorAsync e transmitir a pose de onde você quer colocar a âncora.

    async void CreateAnchorAsync(ARAnchorManager manager, Pose pose) {
        var result = await manager.TryAddAnchorAsync(pose);
        if (result.status.IsError()) {
            // handle error
            return;
        }
        var anchor = result.value;
    }
  • Em seguida, temos a remoção de âncoras.

    void RemoveAnchor(ARAnchorManager manager, ARAnchor anchor) {
        var result = manager.TryRemoveAnchor(anchor.trackableId);
        if (result.status.IsError()) {
            // handle error
            return;
        }
    }
    
    void DestroyAnchorComponent(ARAnchor anchor) {
        Destroy(anchor);
    }
  • E, da mesma forma, é praticamente uma linha de código.

  • Chame TryRemoveAnchor e transmita o ID rastreável da âncora.

  • Quando a âncora foi criada, ela já recebeu um ID rastreável.

  • E temos TrySaveAnchorAsync.

    async void SaveAnchorAsync(ARAnchorManager manager, ARAnchor anchor) {
        var result = await manager.TrySaveAnchorAsync(anchor);
        if (result.status.IsError()) {
            // handle error
            return;
        }
    
        // Save this value, then return it as an input parameter
        SerializableGuid guid = result.value;
    }
  • Você transmite uma âncora de RA como entrada.

  • Essa função retorna um SerializableGuid que identifica a âncora no armazenamento permanente.

  • Depois, você pode usar o GUID ao carregar a âncora.

  • E isso nos leva ao carregamento de âncoras.

    async void LoadAnchorAsync(ARAnchorManager manager, SerializableGuid guid) {
        var result = await manager.TryLoadAnchorAsync(guid);
        if (result.status.IsError()) {
            // handle error
            return;
        }
    
        ARAnchor anchor = result.value;
    }
  • A função a ser chamada aqui é TryLoadAnchorAsync, e você transmite o GUID serializado de antes.

  • Ela vai retornar uma âncora de RA como resultado.

  • É basicamente isso.

  • Essas funções permitem gerenciar facilmente as âncoras locais e persistentes.

  • Portanto, o rastreamento de âncoras é uma tarefa bastante cara na maioria das plataformas de RA.

  • Ao trabalhar com âncoras, considere as seguintes práticas recomendadas: evite criar várias âncoras muito próximas umas das outras, considere se é possível usar uma âncora próxima em vez de criar outra, remova as âncoras quando não estiver mais usando-as e, por fim, se você ativar outro recurso de RA para ajudar a calcular a pose desejada para uma âncora, considere se é possível desativar esse recurso depois que a âncora for criada.

  • Agora, vou passar para a Levana.

SDK do Android XR para Unity

  • Obrigada, Jennifer.

  • Agora, vamos falar sobre a contribuição do Google na jornada do Android XR no Unity.

  • Além dos plug-ins do Unity OpenXR que a Jennifer apresentou, o Google oferece o SDK do Android XR para Unity com recursos adicionais disponíveis na plataforma Android XR.

  • Esse SDK contém muitos recursos e pacotes. Nesta palestra, vamos focar no pacote de extensão do Android XR para Unity.

  • Assim, de forma semelhante ao Android XR e às Entidades Espaciais do OpenXR, o pacote de extensão do Android XR para Unity é, na verdade, um provedor do OpenXR.

  • A arquitetura desse pacote é assim, e eles podem trabalhar em paralelo ou de forma independente.

  • Portanto, como todos os outros provedores do OpenXR, o pacote do Google foi criado diretamente na interface padrão do OpenXR.

  • Aqui, mostramos vários recursos em uma comparação com todos os outros provedores.

  • Assim, você pode decidir quando e por que escolher uma em vez de outra.

  • Talvez você tenha uma dúvida sobre o marcador de entidade rastreável e espacial mostrado nesta tabela.

  • Uma observação: para quem já cria apps e experiências no Android XR, oferecemos esses recursos por meio de extensões rastreáveis que só funcionam no Android XR.

  • Depois, como a Jennifer mencionou, trabalhamos como um grupo aberto do OpenXR e lançamos a extensão de entidades espaciais no lado direito, oferecendo uma experiência consistente e multiplataforma.

  • No momento, estamos descontinuando a extensão rastreável em favor do framework de entidades espaciais.

  • Além de ter um desempenho muito melhor, ele também oferece suporte multiplataforma.

Como criar com entidades espaciais

  • Em seguida, vamos analisar as entidades espaciais.

  • Além do que a Jennifer mencionou sobre planos, ray casting e âncoras, esse recurso também é compatível com provedores de entidades espaciais, como marcadores, que podem detectar e decodificar códigos de barras 2D padrão e rastrear a posição deles no espaço 3D, e a imagem, que reconhece gráficos 2D conhecidos e os rastreia no espaço 3D.

  • E, em seguida, a caixa delimitadora, que vai identificar o objeto físico, como teclado, laptop ou mouse, e rastrear a caixa delimitadora em uma pose 3D.

  • No próximo exemplo, vamos configurar o recurso de caixa delimitadora fornecido pelo pacote de extensões do Google.

  • Essa visualização é praticamente a mesma para todos os recursos do OpenXR.

  • Então, basta mudar para a plataforma Android XR, ativar o provedor do OpenXR e selecionar o recurso do OpenXR que você quer usar. Por exemplo, o recurso de caixa delimitadora de entidade espacial foi mostrado aqui. Depois, corrija os problemas de validação do projeto.

  • Ele ajuda a encontrar todas as dependências exigidas por um determinado recurso e, em seguida, resolver os conflitos causados por vários recursos que contribuem para o mesmo subsistema.

  • Às vezes, você Na maioria das vezes, só precisa escolher um recurso se quiser usar, por exemplo, âncora, plano ou caixa delimitadora aqui.

  • Por fim, você pode criar a cena de exemplo ou de teste.

  • Para acessar o objeto rastreável no momento da execução, basta adicionar o componente AR Bounding Box Manager, que é semelhante ao AR Anchor Manager, e usar a interface do AR Foundation para acessá-lo.

  • Como alternativa, você também pode importar a amostra de entidade espacial fornecida pelo nosso pacote de extensão como um modelo para começar.

  • Esta é a principal diferença ao usar o recurso AR Foundation no Android XR.

  • Para entender o ambiente ao redor do usuário, o app geralmente precisa de acesso aos dados sensíveis do ambiente.

  • E, para proteger o usuário, o Android XR restringe o sistema, ou seja, o acesso aos dados por trás das permissões.

  • Talvez você já conheça isso, como a chamada de permissão normal do Android, como o acesso à câmera ou à localização, coisas desse tipo.

  • A prática recomendada aqui é desativar o componente do gerenciador na inicialização, seja no editor, como você pode ver no lado direito, ou no script, como o evento Awake.

    void Awake() {
        planeManager = GetComponent<ARPlaneManager>();
        planeManager.enabled = false;
        boundingBoxManager = GetComponent<ARBoundingBoxManager>();
        boundingBoxManager.enabled = false;
        permissionUtil = GetComponent<AndroidXRPermissionUtil>();
    }
    
    void OnEnable() {
        StartCoroutine(WaitForPermissions());
    }
  • Depois de conceder todas as permissões necessárias, você pode ativar o gerenciador no script, como o auxiliar WaitForPermissions faz aqui.

    IEnumerator WaitForPermissions() {
        planeManager.enabled = false;
        boundingBoxManager.enabled = false;
    
        yield return new WaitUntil(() =>
            permissionUtil.AllPermissionGranted());
    
        // Enable after granted permissions and
        // restart subsystems.
        planeManager.enabled = true;
        boundingBoxManager.enabled = true;
    
        // Save permission status.
        permissionGranted = true;
    }
  • Ao fazer isso, você evita uma falha de inicialização do subsistema causada por permissões insuficientes.

  • E este é um recurso especial.

  • Como a Jennifer explicou sobre a âncora usando o AR Foundation, para expandir a capacidade de âncora no Android XR, nosso pacote também oferece um novo recurso chamado "âncoras compartilháveis".

  • Esse recurso replica o que o recurso de âncora do AR Foundation oferece atualmente e também vem com algumas funcionalidades adicionais, como âncoras geoespaciais.

  • E, como você pode imaginar, a âncora é a ponte real que conecta o mundo virtual ao físico.

  • A Jennifer explicou como criar, salvar e carregar esses dados, mas tudo isso aconteceu em um espaço local, como a sala de estar do usuário.

  • Mas e o resto do mundo?

  • E como podemos compartilhar isso uns com os outros?

API Geospatial

  • É aí que entra a API Geospatial.

  • Ele permite criar uma âncora geoespacial com base em um local do mundo real, como sua livraria favorita ou um ponto de encontro em um grande parque.

  • Assim, a API Geospatial pode fornecer um rastreador de geoposicionamento preciso usando o VPS, também conhecido como sistema de posicionamento virtual, como um GPS, mas usando os dados do Street View para fornecer resultados de rastreamento muito mais precisos.

  • Alguns de vocês já devem conhecer essa visualização se tiverem experiência com o recurso geoespacial do ARCore.

  • Para acessar a API Geospatial no Android XR, primeiro precisamos nos conectar ao back-end hospedado na plataforma do Google Cloud.

  • Como o back-end geoespacial é alimentado pelo serviço do ARCore no Google Cloud, você pode seguir exatamente as mesmas etapas para configurar seu projeto na nuvem do Google Cloud com acesso à API ARCore.

  • Tudo isso vai permitir o uso do recurso do Google Cloud para Android XR fornecido pelo nosso pacote de extensão.

  • Depois de ativar a API Geospatial e pegar a chave de API do projeto do Google Cloud, você pode ativar esse recurso e configurar a autenticação no menu de configurações do OpenXR, como mostrado aqui, ou configurar manualmente usando a API de script chamada TrySetAuthenticationAsync.

    async Task TrySetAuthentication() {
        googleCloudFeature =
            OpenXRSettings.Instance
                .GetFeature<XRGoogleCloudFeature>();
        var result = await googleCloudFeature
            .TrySetAuthenticationAsync(
                strategy, credential);
        if (result.IsSuccess()) {
            // Ready to use for geospatial tracker.
        } else if (result.IsUnsupported())  {
            // Google Cloud feature is not supported
        } else if (result.IsKeylessError()) {
            // Confirm if keyless has been set up properly.
        } else {
            // Handling other common OpenXR errors.
        }
    }
  • No momento, a plataforma Android XR só aceita autenticação por chave de API, mas vamos oferecer suporte a mais credenciais no futuro.

  • Depois de autenticar, use um gerenciador geoespacial para acessar os recursos geoespaciais.

  • É altamente recomendável verificar a cobertura do VPS no Google Maps antes da integração.

  • Por isso, você também precisa ter acesso à rede ao usar o recurso.

  • O XR Geospatial Manager funciona de maneira semelhante ao componente AR Session fornecido pela AR Foundation.

  • Por isso, ela vem com uma propriedade de estado estático para indicar o suporte do sistema e o estado de rastreamento do rastreador geoespacial.

  • Você pode registrar um evento de mudança de estado por um callback como este.

    void OnGeospatialStateChanged(XRGeospatialStateChangedEventArgs eventArgs) {
        bool isInitFailed = eventArgs.CurrState == XRGeospatialState.InitializationFailed;
        if (isInitFailed && XRGeospatialManager.InitializationResult.IsCloudAuthError()) {
            // Handle cloud authentication issues.
        } else if (isInitFailed) {
            // Check XRGeospatialManager.InitializationResult for other common OpenXR errors.
        } else {
            // Iterate runtime state change, and handle accordingly.
        }
    }
    
    private void OnEnable() {
        XRGeospatialManager.OnStateChanged += OnGeospatialStateChanged;
    }
  • Quando o estado geoespacial estiver em execução, você poderá usar essa instância do gerenciador para todas as funcionalidades a seguir.

  • Primeiro, para verificar a disponibilidade do VPS com a localização de GPS fornecida, usamos a API Location do Unity para receber o valor do GPS e, em seguida, verificar a disponibilidade do VPS.

    async Task CheckVPSAvailability(CancellationToken token) {
        var location = Input.location.lastData;
        try {
            var result = await geospatialManager.TryCheckVPSAvailabilityAsync(
                location.latitude, location.longitude);
            token.ThrowIfCancellationRequested();
            if (result.status.nativeStatusCode == (int)XrResultAndroid.GeospatialCoordinateInvalid) {
                // Invalid coordinates, try with another location.
            } else if (result.status.IsError()) {
                // Handle common OpenXR error: result.status.ToOpenXRStatus()
            }  else if (result.value == XRVPSAvailability.Available)  {
                // You may use this pose to attach geospatial anchors.
                var currentGeospatialPose = new XRGeospatialPose(location);
            }
        }
    }
  • Portanto, essa é basicamente uma substituição se você não quiser verificar o suporte do VPS pelo mapa, mas precisar sair para verificar o status real do GPS.

  • Em seguida, você também pode converter a pose do Unity em uma pose geoespacial usando TryLocate.

    // Geospatial Pose -> Unity Pose
    var geospatialPose =
        new XRGeospatialPose(Input.location.lastData);
    if (geospatialManager.TryLocate(
            geospatialPose, out XRPoseResult result)) {
        if (result.IsPositionValid ||
            result.IsPositionTracked) {
            transform.position = result.Pose.position;
        }
        if (result.IsRotationValid ||
            result.IsRotationTracked) {
            transform.rotation = result.Pose.rotation;
        }
    }
    // Unity Pose -> Geospatial Pose
    Pose pose = new Pose(
        transform.position, transform.rotation);
    if (geospatialManager.TryLocate(
          pose, out XRGeospatialPoseResult result)) {
        if (result.IsPositionValid ||
            result.IsRotationValid) {
            // You may use for anchor attachment.
        }
    }
  • E, usando o resultado da verificação do VPS ou da conversão de pose, você pode anexar a âncora espacial a uma determinada pose geoespacial ou a um tipo de superfície conhecido, como terreno ou telhado.

    async void PlaceAnchor(XRGeospatialPose pose) {
        try {
            Result<ARShareableAnchor> anchorResult;
            XRGeospatialSurfaceType typeToPlace = /* Choose your target type */;
            if (typeToPlace == XRGeospatialSurfaceType.Default) {
                anchorResult = geospatialManager.TryAttachGeospatialAnchor(pose);
            } else {
                pose.Altitude = 0;
                anchorResult = await geospatialManager.TryAttachSurfaceAnchorAsync(typeToPlace, pose);
            }
            if (anchorResult.status.IsSuccess()) {
                // ARShareableAnchorManager will track the anchor and update it.
            } else {
                // Handle OpenXR failures.
            }
        }
    }
  • E, ao juntar tudo isso, você pode criar uma experiência espacial verdadeiramente mágica com o mundo real em destaque.

  • Por isso, colocamos uma seta para guiar o público até o local desejado no mundo real.

  • Ok.

  • O SDK do Android XR não é o único pacote que oferecemos aos desenvolvedores do Unity.

  • O SDK do Android XR do Google para Unity agora também inclui o framework de interação do Android XR e o pacote de áudio do Android XR.

  • Estamos muito felizes em expandir o SDK do Android XR com mais suporte a recursos e mais entidades espaciais.

Finalização e recursos

  • Certo, chegamos ao fim da sessão.

  • Você pode acompanhar o roteiro da Unity on-line para saber o que vem a seguir.

  • Não se esqueça de que o Unity 7, a próxima geração do Unity, será lançado no início do ano que vem.

  • Enquanto isso, você pode testar essas ferramentas e criar um projeto usando o modelo de realidade mista ou dar uma olhada no projeto de amostras do AR Foundation no nosso GitHub.

  • Para saber mais sobre a entidade espacial e nosso suporte ao pacote do Unity, acesse a página no site para desenvolvedores Android.

  • E, por fim, agradeço a todos.

  • Mal podemos esperar para ver o que você vai criar com o AR Foundation e a entidade espacial no Android XR.

Código

Snippets de código

Snippet em C# aos 10:34 em "Âncoras locais e persistência"
async void CreateAnchorAsync(ARAnchorManager manager, Pose pose) {
    var result = await manager.TryAddAnchorAsync(pose);
    if (result.status.IsError()) {
        // handle error
        return;
    }
    var anchor = result.value;
}
Snippet em C# aos 10:43 em "Âncoras locais e persistência"
void RemoveAnchor(ARAnchorManager manager, ARAnchor anchor) {
    var result = manager.TryRemoveAnchor(anchor.trackableId);
    if (result.status.IsError()) {
        // handle error
        return;
    }
}

void DestroyAnchorComponent(ARAnchor anchor) {
    Destroy(anchor);
}
Snippet em C# às 11:00 em "Âncoras locais e persistência"
async void SaveAnchorAsync(ARAnchorManager manager, ARAnchor anchor) {
    var result = await manager.TrySaveAnchorAsync(anchor);
    if (result.status.IsError()) {
        // handle error
        return;
    }

    // Save this value, then return it as an input parameter
    SerializableGuid guid = result.value;
}
Snippet em C# aos 11:17 em "Âncoras locais e persistência"
async void LoadAnchorAsync(ARAnchorManager manager, SerializableGuid guid) {
    var result = await manager.TryLoadAnchorAsync(guid);
    if (result.status.IsError()) {
        // handle error
        return;
    }

    ARAnchor anchor = result.value;
}
Snippet em C# aos 16:45 em "Como criar com entidades espaciais"
void Awake() {
    planeManager = GetComponent<ARPlaneManager>();
    planeManager.enabled = false;
    boundingBoxManager = GetComponent<ARBoundingBoxManager>();
    boundingBoxManager.enabled = false;
    permissionUtil = GetComponent<AndroidXRPermissionUtil>();
}

void OnEnable() {
    StartCoroutine(WaitForPermissions());
}
Snippet em C# aos 16:58 em "Como criar com entidades espaciais"
IEnumerator WaitForPermissions() {
    planeManager.enabled = false;
    boundingBoxManager.enabled = false;

    yield return new WaitUntil(() =>
        permissionUtil.AllPermissionGranted());

    // Enable after granted permissions and
    // restart subsystems.
    planeManager.enabled = true;
    boundingBoxManager.enabled = true;

    // Save permission status.
    permissionGranted = true;
}
Snippet em C# aos 19:12 em "API Geospatial"
async Task TrySetAuthentication() {
    googleCloudFeature =
        OpenXRSettings.Instance
            .GetFeature<XRGoogleCloudFeature>();
    var result = await googleCloudFeature
        .TrySetAuthenticationAsync(
            strategy, credential);
    if (result.IsSuccess()) {
        // Ready to use for geospatial tracker.
    } else if (result.IsUnsupported())  {
        // Google Cloud feature is not supported
    } else if (result.IsKeylessError()) {
        // Confirm if keyless has been set up properly.
    } else {
        // Handling other common OpenXR errors.
    }
}
Snippet em C# aos 20:24 em "API Geospatial"
void OnGeospatialStateChanged(XRGeospatialStateChangedEventArgs eventArgs) {
    bool isInitFailed = eventArgs.CurrState == XRGeospatialState.InitializationFailed;
    if (isInitFailed && XRGeospatialManager.InitializationResult.IsCloudAuthError()) {
        // Handle cloud authentication issues.
    } else if (isInitFailed) {
        // Check XRGeospatialManager.InitializationResult for other common OpenXR errors.
    } else {
        // Iterate runtime state change, and handle accordingly.
    }
}

private void OnEnable() {
    XRGeospatialManager.OnStateChanged += OnGeospatialStateChanged;
}
Snippet em C# aos 20:38 em "API Geospatial"
async Task CheckVPSAvailability(CancellationToken token) {
    var location = Input.location.lastData;
    try {
        var result = await geospatialManager.TryCheckVPSAvailabilityAsync(
            location.latitude, location.longitude);
        token.ThrowIfCancellationRequested();
        if (result.status.nativeStatusCode == (int)XrResultAndroid.GeospatialCoordinateInvalid) {
            // Invalid coordinates, try with another location.
        } else if (result.status.IsError()) {
            // Handle common OpenXR error: result.status.ToOpenXRStatus()
        }  else if (result.value == XRVPSAvailability.Available)  {
            // You may use this pose to attach geospatial anchors.
            var currentGeospatialPose = new XRGeospatialPose(location);
        }
    }
}
Snippet em C# aos 21:03 em "API Geospatial"
// Geospatial Pose -> Unity Pose
var geospatialPose =
    new XRGeospatialPose(Input.location.lastData);
if (geospatialManager.TryLocate(
        geospatialPose, out XRPoseResult result)) {
    if (result.IsPositionValid ||
        result.IsPositionTracked) {
        transform.position = result.Pose.position;
    }
    if (result.IsRotationValid ||
        result.IsRotationTracked) {
        transform.rotation = result.Pose.rotation;
    }
}
Snippet em C# aos 21:03 em "API Geospatial"
// Unity Pose -> Geospatial Pose
Pose pose = new Pose(
    transform.position, transform.rotation);
if (geospatialManager.TryLocate(
      pose, out XRGeospatialPoseResult result)) {
    if (result.IsPositionValid ||
        result.IsRotationValid) {
        // You may use for anchor attachment.
    }
}
Snippet em C# aos 21:11 em "API Geospatial"
async void PlaceAnchor(XRGeospatialPose pose) {
    try {
        Result<ARShareableAnchor> anchorResult;
        XRGeospatialSurfaceType typeToPlace = /* Choose your target type */;
        if (typeToPlace == XRGeospatialSurfaceType.Default) {
            anchorResult = geospatialManager.TryAttachGeospatialAnchor(pose);
        } else {
            pose.Altitude = 0;
            anchorResult = await geospatialManager.TryAttachSurfaceAnchorAsync(typeToPlace, pose);
        }
        if (anchorResult.status.IsSuccess()) {
            // ARShareableAnchorManager will track the anchor and update it.
        } else {
            // Handle OpenXR failures.
        }
    }
}