Android XR

Cómo diseñar contenido espacial en Android XR con Unity

Bocinas

  • Levana Chen

    Ingeniero de software

  • Jennifer Stanton

    Ingeniero de software sénior

Acerca de

Acerca de la charla

Descubre cómo fijar y mantener experiencias en 3D en el mundo real con Unity y Android XR. En esta sesión, se abordan el framework de Spatial Entities, los Cloud Anchors y las APIs de Geospatial, y se muestra cómo crear apps adaptadas al contexto que recuerden las ubicaciones físicas y sincronicen los datos espaciales multiusuario en todas las sesiones.

Examinaremos la arquitectura detrás de las entidades espaciales y comprenderemos cómo fijar recursos digitales a objetos físicos, superficies y ubicaciones geográficas. Te irás con flujos de trabajo prácticos de Unity para mapear espacios, conservar contenido en todas las sesiones y crear experiencias de RA/RE compartidas y con reconocimiento de la ubicación.

Resumen

  • AR Foundation proporciona una API de secuencias de comandos unificada en todas las plataformas de XR con extensiones de OpenXR. Te permite representar y consultar atributos del mundo real, como planos y mallas.
  • Los anclajes persistentes estabilizan el contenido digital en todas las sesiones y los reinicios del dispositivo. Puedes conservarlos con TrySaveAnchorAsync y volver a cargarlos con GUID serializados.
  • El framework de Spatial Entities reemplaza las extensiones de seguimiento para proporcionar compatibilidad multiplataforma y un mejor rendimiento para el seguimiento de elementos como cuadros delimitadores y marcadores.
  • Los componentes del administrador deben estar inhabilitados hasta que se otorguen los permisos de Android XR. Esto evita fallas de inicialización del subsistema causadas por el acceso restringido a datos sensibles del entorno.
  • La API de Geospatial usa los servicios de ARCore de Google Cloud y el VPS para posicionar contenido en ubicaciones exteriores del mundo real.

Recursos

Gemini Notebook

Temas

  • android-xr
  • unidad
  • ar-foundation
  • openxr
  • spatial-entities
  • taquetes
  • geospatial-api

Transcripción

Descargar transcripción

Introducción y descripción general de AR Foundation

  • Bien.

  • Hola a todos.

  • Este es el curso Arquitectura de contenido espacial en Android XR con Unity.

  • Me llamo Jennifer Stanton.

  • Trabajo en Unity como ingeniero de software sénior.

  • Trabajo en el equipo de funciones de XR, específicamente en AR Foundation y los paquetes relacionados que llevan la realidad aumentada y mixta a Unity.

  • Soy Levana Chen, del equipo de Motores de juegos de RE de Google.

  • Nuestros equipos se enfocaron en ofrecer complementos y paquetes para brindar una funcionalidad de RE mejorada y las integraciones fluidas de motores de juegos.

  • Uno de los mayores desafíos que nos comentan es que brindar compatibilidad con varias plataformas de RE con la misma base de código requiere mucho trabajo.

  • AR Foundation es la capa de la API de realidad extendida de alto nivel de Unity.

  • Puedes orientar tus proyectos a varias plataformas de RE sin tener que reescribir el código de forma significativa ni administrar varias bases de código. Además, te brinda una API de secuencias de comandos para las funciones de RA en cualquier plataforma.

  • Esto te permite enfocarte en crear tu app, juego o experiencia, y Unity se encarga de los detalles de la plataforma por ti.

  • Una forma en que AR Foundation logra esto es a través de las extensiones de OpenXR.

  • Se trata de un conjunto de APIs abiertas y estándar de la industria que define Khronos Group.

  • OpenXR también creó entidades espaciales.

  • Es un framework para que el contenido digital represente el mundo físico y, además, interactúe con él.

  • Las entidades espaciales proporcionan un modelo unificado para representar elementos del mundo real como objetos digitales.

  • Me complace compartir contigo información reciente sobre AR Foundation para que puedas comenzar tu recorrido y crear experiencias de RE.

  • A continuación, repasaré las capacidades de AR Foundation para que tu contenido digital pueda interactuar con el mundo real.

  • Luego, revisaré la configuración del proyecto, incluidos los paquetes y otras dependencias, para que puedas implementarla en tus proyectos.

  • Para terminar, repasaré algunas funciones exclusivas de Android XR.

Funciones clave de AR Foundation

  • Por lo tanto, algunas de las formas en que AR Foundation representa el mundo real de forma digital son los planos.

  • Estas son superficies planas en el entorno físico, como pisos, paredes, techos y, también, mesas y sofás.

  • Las mallas son estructuras en 3D que representan la geometría del mundo físico.

  • Y también tenemos formas de interactuar con el mundo real, las proyecciones de rayos.

  • Estos determinan dónde se cruza un rayo con el contenido digital.

  • Piensa en él como un puntero láser, y obtendrás información sobre dónde está brillando ese puntero láser.

  • También tenemos anclas, que ayudan a estabilizar y reubicar un punto en el espacio.

  • Más adelante en esta presentación, profundizaré en los anclajes.

  • Por lo tanto, estas cuatro se consideran funciones de AR Foundation.

  • También hay algunas funciones más que no se mencionan en esta diapositiva.

  • Específicamente, los planos y los anclajes se consideran rastreables, ya que extienden la clase ARTrackable, y sus administradores hacen un seguimiento de las actualizaciones desde el tiempo de ejecución.

  • Así que, hablemos de los planes.

  • Para los planos, tenemos el componente ARPlane, que proporciona identificación en tiempo real de superficies planas.

  • Tienen etiquetas semánticas que puedes consultar para saber si tu plano es un piso, una mesa, una pared, etcétera.

  • Los planos también tienen límites dinámicos, por lo que, a medida que el usuario se mueva por el mundo real y pueda ver más superficies, los límites de los planos se expandirán, se fusionarán y se definirán de forma dinámica en tiempo real.

  • También podemos adjuntar un colisionador de malla al plano para controlar la física.

  • Aquí puedes ver un ejemplo de detección de planos.

  • Esta es la escena de proyección de rayos de las muestras de AR Foundation que se ejecuta en un dispositivo Android XR.

  • Detecta polígonos 2D dinámicos en tiempo real.

  • Puedes compilar una app que tenga esta funcionalidad siguiendo nuestra guía de configuración de proyectos o usando una de nuestras muestras o plantillas.

  • A continuación, tenemos las mallas.

  • Las mallas son una función de RA que proporciona mallas 3D del entorno.

  • Podemos adjuntar un colisionador de malla a estas mallas generadas, lo que permite que tu contenido digital interactúe con objetos del mundo real.

  • Las mallas permiten una oclusión de objetos convincente.

  • Por lo tanto, un objeto virtual puede parecer que está detrás de un objeto físico.

  • Si tu objeto digital se puede mover en el espacio, puedes usar la misma geometría para encontrar una ruta que evite los objetos del mundo real.

  • A continuación, tenemos el trazado de rayos.

  • La proyección de rayos proyecta rayos virtuales en tu escena en 3D para buscar intersecciones sin que tengas que preocuparte por las matemáticas complejas.

  • El rayo proyectado de Project podría cruzarse con varios objetos 3D de tu entorno.

  • Puedes configurar la proyección de rayos para que solo alcance ciertos tipos de contenido digital.

  • Por ejemplo, puedes configurarlo para que no alcance planos y solo se cruce con mallas.

Configuración de paquetes y dependencias

  • Ahora, veamos los paquetes relevantes.

  • Todos estos paquetes funcionan en conjunto para comunicarse entre sí y crear una experiencia de RE completa.

  • Como se mencionó, AR Foundation controla funciones como planos y anclajes.

  • El complemento de OpenXR controla las APIs nativas en varias plataformas de XR, por lo que te recomendamos usar este paquete si tu dispositivo usa OpenXR.

  • El complemento de OpenXR se puede vincular de forma opcional con el paquete de Spatial Entities de OpenXR para acceder específicamente a las extensiones de Spatial Entities, y más adelante se brindará más información al respecto.

  • Si sabes que te orientarás específicamente a dispositivos Android XR, como los visores de realidad extendida y los lentes de realidad extendida con cable, se necesita el paquete de Unity OpenXR para Android XR.

  • Y, como todo esto sigue el patrón de complemento, el impacto en tu código debería ser mínimo.

  • No todas las funciones están disponibles en todos los paquetes de AR Foundation.

  • Por ejemplo, si observas este gráfico, la creación de mallas no está disponible actualmente en el paquete de entidades espaciales de OpenXR de Unity.

  • XR Plug-in Management te permite administrar qué funciones de OpenXR se seleccionan en tu proyecto.

  • Por lo tanto, si estás en el editor de Unity, ve a Edit, configuración del proyecto y, luego, XR Plug-in Management estará en la barra lateral izquierda.

  • Aquí puedes encontrar las funciones y los grupos de funciones de OpenXR, de modo que puedas seleccionar y anular la selección de las funciones y los grupos de funciones que quieras incluir en tu compilación.

  • Por ejemplo, en esta captura de pantalla, vemos todas las que vienen con el paquete de OpenXR de Android XR.

  • Y, luego, puedes mezclarlas y combinarlas con entidades espaciales, por ejemplo, si quisieras.

  • Aquí está la ventana del Administrador de paquetes.

  • Destaqué algunos de los paquetes que podrías ver en una configuración típica de un proyecto de RE.

  • Como puedes ver, tenemos AR Foundation, que ya se mencionó.

  • También tenemos el complemento de OpenXR.

  • Tenemos el paquete de Android XR.

  • También destaqué algunas de otras plataformas, ya que puedes crear un proyecto que se compile para varias plataformas.

  • Y, luego, también tenemos en la parte inferior derecha algunos otros paquetes.

  • Composition Layers, que funciona con dispositivos OpenXR; Core Utils, muy útil para todo lo relacionado con la RE; y XR Hands y XR Interaction Toolkit para obtener tu entrada, que es bastante esencial.

  • A continuación, tenemos la validación del proyecto.

  • Por lo tanto, esto forma parte de XR Plug-in Management.

  • La validación del proyecto puede detectar funciones duplicadas, así como otros problemas en tu proyecto que debes corregir para que se ejecute.

  • Sin embargo, en esta captura de pantalla, destaqué los atributos duplicados.

  • Básicamente, esto significa que dos de las mismas funciones, como, por ejemplo, anclajes, planos y proyecciones de rayos,

  • El usuario seleccionó incluir duplicados de estas funciones de varios paquetes, y solo se le solicita que seleccione uno o el otro.

Anclajes locales y persistencia

  • Esto nos lleva a las anclas locales y la persistencia.

  • Los anclajes garantizan que el contenido digital permanezca en las ubicaciones deseadas del entorno, independientemente de los cambios en el estado de seguimiento de la sesión de RA.

  • Las plataformas de RA actualizan automáticamente las poses de los anclajes con el tiempo para garantizar que permanezcan en una posición coherente, y los anclajes son la mejor manera de asegurarse de que tu contenido permanezca en su lugar si te alejas de tu anclaje y luego vuelves a él.

  • ¿Y qué sucede cuando el usuario cierra la app, la reinicia más tarde y vuelve a ella en una sesión independiente?

  • Los anclajes persistentes te permiten guardar anclajes en una sesión de RA y, luego, cargarlos en sesiones posteriores.

  • Sobreviven a los ciclos de vida de la app y a los reinicios del dispositivo.

  • Aquí se muestra nuestro ejemplo de anclajes persistentes en el proyecto de muestras de AR Foundation.

  • La escena de muestra tiene un menú que incluye todas las funciones compatibles con esa plataforma, como guardar y cargar anclas.

  • Y eso nos lleva al ciclo de vida de los anclajes persistentes.

  • Primero, crearías un ancla de forma local, por lo que aún no se guardaría en ningún lugar, no se guardaría en el almacenamiento persistente, solo sería un ancla local.

  • Luego, lo conservarías en el almacenamiento.

  • Después de eso, puedes reiniciar la app y, luego, cargarla desde el almacenamiento.

  • Algunas plataformas, como Android XR, también admiten el borrado o la despersistencia de las anclas.

  • El proveedor de Spatial Entities admite la carga automática de todos los anclajes guardados para que no tengas que solicitar manualmente cada anclaje por su ID.

  • En la configuración de XR Plug-in Management, puedes seleccionar la opción Automatically Load Saved Anchors en la función Spatial Entities: Anchors.

  • Y guardar un ancla solo requiere unas pocas líneas de código.

  • Primero, comenzamos en el editor de Unity y nos aseguramos de que tu escena esté lista agregando el componente AR Anchor Manager a tu objeto de juego XR Origin.

  • El administrador mantiene la escena actualizada con las anclas de seguimiento del tiempo de ejecución.

  • Esto nos lleva al código.

  • Para agregar un ancla, puedes llamar a TryAddAnchorAsync y pasar la pose de donde deseas colocarla.

    async void CreateAnchorAsync(ARAnchorManager manager, Pose pose) {
        var result = await manager.TryAddAnchorAsync(pose);
        if (result.status.IsError()) {
            // handle error
            return;
        }
        var anchor = result.value;
    }
  • A continuación, veremos cómo quitar anclas.

    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);
    }
  • Y, de manera similar, es prácticamente una sola línea de código.

  • Llamas a TryRemoveAnchor y pasas el ID de seguimiento del ancla.

  • Cuando se creó el ancla, ya se le asignó un ID de seguimiento.

  • Y, luego, tenemos 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;
    }
  • Pasas un ancla de RA como entrada.

  • Esta función devuelve un SerializableGuid que identifica el ancla en el almacenamiento persistente.

  • Luego, puedes usar el GUID cuando cargues el ancla.

  • Y eso nos lleva a cargar anclas.

    async void LoadAnchorAsync(ARAnchorManager manager, SerializableGuid guid) {
        var result = await manager.TryLoadAnchorAsync(guid);
        if (result.status.IsError()) {
            // handle error
            return;
        }
    
        ARAnchor anchor = result.value;
    }
  • La función a la que se debe llamar aquí es TryLoadAnchorAsync, y debes pasar el GUID serializado de antes.

  • Como resultado, se devolverá un ancla de RA.

  • Y eso es todo.

  • Estas funciones te permiten administrar fácilmente las anclas locales y persistentes.

  • Por lo tanto, el seguimiento de anclajes es una tarea bastante costosa en la mayoría de las plataformas de RA.

  • Cuando trabajes con anclas, ten en cuenta las siguientes prácticas recomendadas: evita crear varias anclas muy cerca unas de otras, considera si puedes usar un ancla cercana en lugar de crear otra, quita las anclas cuando ya no las uses y, por último, si habilitas otra función de RA para ayudar a calcular la pose deseada para un ancla, considera si puedes inhabilitar esa función una vez que se cree el ancla correctamente.

  • Ahora, le daré la palabra a Levana.

SDK de Android XR para Unity

  • Gracias, Jennifer.

  • A continuación, te explicaré cuál es la contribución de Google en el recorrido de Android XR en Unity.

  • Además de los complementos de OpenXR para Unity que Jennifer presentó hasta ahora, Google proporciona el SDK de Android XR para Unity con funciones adicionales que están disponibles en la plataforma de Android XR.

  • Este SDK contiene muchas funciones y paquetes, y en esta charla, nos enfocaremos en el paquete de Android XR Extension para Unity.

  • Por lo tanto, de manera similar a OpenXR Android XR y OpenXR Spatial Entities, el paquete de Android XR Extension for Unity es, en realidad, un proveedor de OpenXR.

  • La arquitectura de este paquete se ve así, y pueden trabajar en paralelo o de forma independiente.

  • Por lo tanto, al igual que todos los demás proveedores de OpenXR, el paquete de Google se basa directamente en la interfaz estándar de OpenXR.

  • Aquí mostramos un conjunto de funciones como una comparación entre todos los demás proveedores.

  • Por lo tanto, puedes ayudarte a tomar una decisión sobre cuándo y por qué elegir una opción sobre otra.

  • Por lo tanto, es posible que tengas una pregunta sobre el marcador de entidad espacial y rastreable que se muestra en esta tabla.

  • Como nota al margen, para quienes ya hayan creado apps y experiencias en Android XR, proporcionamos estas funciones a través de las extensiones de seguimiento, que solo funcionan en Android XR.

  • Y, luego, como mencionó Jennifer, trabajar como un grupo abierto de OpenXR y, después, lanzar la extensión de entidades espaciales en el lado derecho y proporcionar una experiencia coherente y multiplataforma.

  • Actualmente, estamos descontinuando la extensión de seguimiento en favor del framework de entidades espaciales.

  • No solo porque esta última tiene un rendimiento mucho mejor, sino también por la compatibilidad multiplataforma.

Cómo compilar con entidades espaciales

  • Luego, analicemos más de cerca las entidades espaciales.

  • Además de lo que Jennifer mencionó sobre los planos, el trazado de rayos y los anclajes, esta función también es compatible con los proveedores de entidades espaciales, como los marcadores, que pueden detectar y decodificar códigos de barras 2D estándar y hacer un seguimiento de su posición en el espacio 3D, y la imagen, que reconocerá gráficos 2D conocidos y hará un seguimiento de ellos en el espacio 3D.

  • Y, luego, el cuadro delimitador, que identificará el objeto físico, como un teclado, una laptop o un mouse, y hará un seguimiento de su cuadro delimitador en una pose en 3D.

  • En el siguiente ejemplo, configuraremos la función de cuadro delimitador que proporciona el paquete de extensiones de Google.

  • Esta vista es prácticamente la misma para todas las funciones de OpenXR.

  • Por lo tanto, primero debes cambiar a la plataforma de Android XR, habilitar el proveedor de OpenXR y seleccionar la función de OpenXR con la que quieres compilar. Por ejemplo, aquí se mostró la función de cuadro delimitador de entidad espacial. Luego, corrige los problemas de validación del proyecto.

  • Te ayudará a encontrar todas las dependencias que requiere una función determinada y, luego, resolver los conflictos que se producen cuando varias funciones contribuyen al mismo subsistema.

  • A veces, solo necesitas elegir una función si quieres usar, por ejemplo, un ancla, un plano o un cuadro delimitador aquí.

  • Y, por último, puedes compilar la escena de muestra o la escena de prueba.

  • Para acceder al objeto rastreable durante el tiempo de ejecución, puedes agregar el componente AR Bounding Box Manager, que es similar al componente AR Anchor Manager, y, luego, usar la interfaz de AR Foundation para acceder a él.

  • Como alternativa, también puedes importar la muestra de entidad espacial que proporciona nuestro paquete de extensión como plantilla para comenzar.

  • Esta es la principal diferencia cuando usas la función de AR Foundation en Android XR.

  • Para comprender el entorno que rodea al usuario, la app suele necesitar acceso a los datos sensibles de ese entorno.

  • Para proteger al usuario, Android XR restringe el acceso a los datos del sistema detrás de los permisos.

  • Es posible que ya conozcas esto, como la llamada de permiso normal de Android, como el acceso a la cámara o a la ubicación, y cosas por el estilo.

  • La práctica recomendada aquí es inhabilitar el componente del administrador al inicio, ya sea desde el editor, como puedes ver en el lado derecho, o desde la secuencia de comandos, como el evento Awake.

    void Awake() {
        planeManager = GetComponent<ARPlaneManager>();
        planeManager.enabled = false;
        boundingBoxManager = GetComponent<ARBoundingBoxManager>();
        boundingBoxManager.enabled = false;
        permissionUtil = GetComponent<AndroidXRPermissionUtil>();
    }
    
    void OnEnable() {
        StartCoroutine(WaitForPermissions());
    }
  • Una vez que hayas otorgado todos los permisos necesarios, puedes habilitar el administrador desde la secuencia de comandos, como lo hace el ayudante WaitForPermissions aquí.

    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;
    }
  • De esta manera, puedes evitar un error de inicialización del subsistema causado por permisos insuficientes.

  • Esta es una función especial.

  • Como Jennifer nos explicó sobre el anclaje con AR Foundation, para expandir la capacidad de anclaje en Android XR, nuestro paquete también proporciona una nueva función llamada anclajes compartibles.

  • Esta función replica lo que actualmente admite la función de anclaje de AR Foundation y también incluye algunas funciones adicionales, como los anclajes geoespaciales.

  • Y, como puedes imaginar, el anclaje es el verdadero puente que conecta el mundo virtual y el físico.

  • Jennifer nos explicó cómo crearlos, guardarlos y cargarlos, pero todo esto sucedió en un espacio local, como la sala de estar del usuario.

  • Pero ¿qué pasa con el resto del mundo?

  • ¿Y cómo podríamos compartirlo entre nosotros?

API de Geospatial

  • Y aquí es donde entra en juego la API de Geospatial.

  • Te permite crear un ancla geoespacial basada en una ubicación del mundo real, como tu librería favorita o un punto de encuentro en un parque grande.

  • Por lo tanto, la API de Geospatial puede brindarte un rastreador de posición geográfica preciso a través del VPS, también conocido como sistema de posicionamiento virtual, como un GPS, pero usa los datos de Street View en exteriores para proporcionar resultados de seguimiento mucho más precisos.

  • Por lo tanto, es posible que algunos de ustedes ya conozcan esta vista si tienen experiencia previa con la función geoespacial de ARCore.

  • Por lo tanto, para acceder a la API de Geospatial en Android XR, primero debemos conectarnos al backend alojado en la plataforma de Google Cloud.

  • Dado que el backend geoespacial en realidad funciona con el servicio de ARCore en Google Cloud, puedes seguir exactamente el mismo paso para configurar tu proyecto de Google Cloud con acceso a la API de ARCore.

  • Todo esto habilitará el uso de la función de Google Cloud para Android XR que proporciona nuestro paquete de extensiones.

  • Una vez que hayas habilitado la API de Geospatial y obtenido la clave de API del proyecto de Google Cloud, podrás habilitar esta función y configurar la autenticación a través del menú de configuración de OpenXR que se muestra aquí. Como alternativa, puedes configurarla de forma manual a través de la API de secuencias de comandos llamada 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.
        }
    }
  • Ten en cuenta que, por el momento, la plataforma de Android XR solo admite la autenticación con clave de API, pero en el futuro se admitirán más credenciales.

  • Por lo tanto, una vez que te hayas autenticado, podrás usar un administrador geoespacial para acceder a las funciones geoespaciales.

  • Se recomienda consultar primero el mapa de Google Maps para conocer la cobertura del VPS antes de la integración.

  • Por lo tanto, también debes tener acceso a la red cuando uses la función.

  • Por lo tanto, el XR Geospatial Manager funciona de manera similar al componente AR Session que proporciona AR Foundation.

  • Por lo tanto, incluye una propiedad de estado estática para indicar la compatibilidad del sistema y el estado de seguimiento del rastreador geoespacial.

  • Puedes registrar un evento de cambio de estado con una devolución de llamada como esta.

    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;
    }
  • Una vez que el estado geoespacial se esté ejecutando, puedes usar esta instancia de administrador para todas las funciones que se indican a continuación.

  • Primero, para verificar la disponibilidad del VPS con la ubicación de GPS proporcionada, usamos la API de ubicación de Unity para obtener el valor de GPS y, luego, verificar la disponibilidad del 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);
            }
        }
    }
  • Por lo tanto, esta es básicamente una alternativa si no quieres verificar la compatibilidad con el VPS a través del mapa, pero debes salir al exterior para verificar el estado real del GPS.

  • Luego, también puedes convertir la pose entre la pose de Unity y la pose geoespacial con 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.
        }
    }
  • Luego, con el resultado de la verificación del VPS o de la conversión de la pose, puedes adjuntar el ancla espacial a una pose geoespacial determinada o a un tipo de superficie conocido, como un terreno o un techo.

    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.
            }
        }
    }
  • Y, luego, cuando combinas todo esto, puedes crear una experiencia espacial verdaderamente mágica con el mundo real en primer plano.

  • Aquí, colocamos una flecha para guiar a nuestro público al lugar objetivo en el mundo real.

  • Bien.

  • Por lo tanto, el SDK de Android XR no es el único paquete que proporcionamos a los desarrolladores de Unity.

  • El SDK de Android XR de Google para Unity ahora también incluye el framework de interacción de Android XR y el paquete de audio de Android XR.

  • Y nos entusiasma mucho expandir el SDK de Android XR con más compatibilidad con funciones y también incluir más entidades espaciales.

Cierre y recursos

  • Muy bien, con esto llegamos al final de la sesión.

  • Puedes seguir la hoja de ruta de Unity en línea para ver qué se viene.

  • No olvides que Unity 7, la próxima generación de Unity, llegará a principios del próximo año.

  • Mientras tanto, puedes probar estas herramientas y crear un proyecto con la plantilla de realidad mixta o echar un vistazo al proyecto de muestras de AR Foundation en nuestro GitHub.

  • Además, para obtener más información sobre Spatial Entity y nuestra compatibilidad con el paquete de Unity, puedes visitar la página en el sitio para desarrolladores de Android.

  • Y, por último, gracias a todos.

  • Estamos ansiosos por ver lo que puedes crear con AR Foundation y Spatial Entity en Android XR.

Código

Fragmentos de código

Fragmento de C# en el minuto 10:34 de "Anclajes locales y persistencia"
async void CreateAnchorAsync(ARAnchorManager manager, Pose pose) {
    var result = await manager.TryAddAnchorAsync(pose);
    if (result.status.IsError()) {
        // handle error
        return;
    }
    var anchor = result.value;
}
Fragmento de C# en el minuto 10:43 de "Anclajes locales y persistencia"
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);
}
Fragmento de C# en el minuto 11:00 de "Anclajes locales y persistencia"
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;
}
Fragmento de C# en el minuto 11:17 de "Anclajes locales y persistencia"
async void LoadAnchorAsync(ARAnchorManager manager, SerializableGuid guid) {
    var result = await manager.TryLoadAnchorAsync(guid);
    if (result.status.IsError()) {
        // handle error
        return;
    }

    ARAnchor anchor = result.value;
}
Fragmento de código de C# en el minuto 16:45 de "Building with spatial entities"
void Awake() {
    planeManager = GetComponent<ARPlaneManager>();
    planeManager.enabled = false;
    boundingBoxManager = GetComponent<ARBoundingBoxManager>();
    boundingBoxManager.enabled = false;
    permissionUtil = GetComponent<AndroidXRPermissionUtil>();
}

void OnEnable() {
    StartCoroutine(WaitForPermissions());
}
Fragmento de código de C# en el minuto 16:58 de "Compila con entidades espaciales"
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;
}
Fragmento de código de C# en el minuto 19:12 de "API de 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.
    }
}
Fragmento de C# en el minuto 20:24 de "API de 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;
}
Fragmento de C# en el minuto 20:38 de "API de 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);
        }
    }
}
Fragmento de C# en el minuto 21:03 de "API de 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;
    }
}
Fragmento de C# en el minuto 21:03 de "API de 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.
    }
}
Fragmento de C# en el minuto 21:11 de "API de 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.
        }
    }
}