Compartir a través de


Arquitectura de los interactivos: MRTK3

MRTK se basa en el conjunto de interactivos ofrecido por XR Interaction Toolkit de Unity. Las características de realidad mixta, como el seguimiento de manos articulado, la mirada y la reducción requieren interactivos más elaborados que el conjunto proporcionado con XRI de manera predeterminada. MRTK define nuevas interfaces de interactivos clasificadas generalmente por la modalidad de entrada y las implementaciones correspondientes.

Resumen y revisión

En el caso de los desarrolladores nuevos en XRI, se recomienda revisar primero la documentación sobre la arquitectura de XRI de Unity. Los interactivos de MRTK son subclases de los interactivos de XRI existentes o implementaciones de las interfaces de los interactivos de XRI. Vea la documentación de Unity sobre su arquitectura de interactivos, que también se aplica a MRTK.

Buenos ciudadanos de XRI

Los interactivos de MRTK personalizados se comportan bien con respecto a las interfaces predeterminadas de los interactivos de XRI; desde la perspectiva de los sistemas de XRI, son indistinguibles de los interactivos convencionales. También es verdad lo contrario: al compilar interactivos avanzados en MRTK, los interactivos de XRI predeterminados siguen funcionando para las operaciones básicas de mantener el puntero y seleccionar. Forma parte del esfuerzo de MRTK el ser totalmente compatible con los proyectos de XRI existentes. Si tiene una aplicación de XRI, los controles de interfaz de usuario y los objetos con los que se puede interactuar de MRTK funcionan con la configuración de XRI convencional existente.

Abstracción de la modalidad de entrada

El dispositivo de entrada, el interactivo que realiza la interacción y los eventos de interacción que generan están todos aislados arquitectónicamente en XRI. Este aislamiento es fundamental para la estrategia de abstracción de entrada de MRTK3, y nos permite escribir interacciones multiplataforma y multidispositivo que funcionan bien en todos los contextos.

A partir de MRTK v2, hay un instinto común de codificar interacciones específicas para un determinado tipo de entrada o dispositivo. Muchos desarrolladores están acostumbrados a escribir interacciones que reaccionan específicamente a un agarre cercano, un rayo lejano o algún otro tipo de entrada específico.

Aunque MRTK3 todavía permite eliminar la ambigüedad y detectar modos de entrada individuales, las interacciones de codificación rígida para tipos de entrada individuales específicos se limitan artificialmente y reducen la flexibilidad de las interacciones. Puede encontrar más información sobre esto en la documentación sobre la arquitectura de los objetos con los que se puede interactuar, pero la clave de los interactivos es que generalmente no tienen que asignar 1:1 con dispositivos de entrada.

AttachTransform e inversión de control

Gran parte de lo que MRTK v2 hacía a la hora de "mover lógicas" como parte de ObjectManipulator, Slider, etc. ahora es responsabilidad del propio interactivo. El interactivo ahora controla su elemento attachTransform para definir cómo se comporta un tipo específico de manipulación. Ya no es necesario escribir lógica de interacción compleja en el objeto con el que se puede interactuar que difiere entre modalidades de entrada, sino que la lógica de manipulación unificada puede escuchar la posición de attachTransform independientemente de la modalidad de entrada o del dispositivo que la controla.

Por ejemplo, un elemento attachTransform de GrabInteractor se encuentra en el punto de agarre en la mano o el controlador. El elemento attachTransform de XRRayInteractor se encuentra en el punto de impacto en el extremo del rayo. El CanvasProxyInteractorde attachTransform se encuentra dondequiera que se haga clic con el mouse. En todos estos distintos interactivos, el objeto con el que se puede interactuar no tiene que preocuparse por el tipo de interactivo para responder adecuadamente a las manipulaciones.

El objeto con el que se puede interactuar consulta a attachTransform y puede tratar cada attachTransform de la misma manera, independientemente del tipo de interactivo.

Este enfoque es fundamental para la compatibilidad con los interactivos de XRI existentes, así como para la corrección futura de las interacciones de las modalidades de entrada que aún no se han desarrollado. Si se incorpora un nuevo método de entrada, no es necesario modificar los objetos con los que se puede interactuar existentes si el nuevo interactivo genera un objeto attachTransform válido y correcto.

Por lo tanto, filosofíamente, es attachTransform la lógica de interacción. En cualquier interacción personalizada, siempre dé preferencia a escribir un nuevo interactivo con una nueva lógica attachTransform en lugar de volver a escribir o ampliar los objetos con los que se puede interactuar a fin de personalizarlos para la nueva interacción. De este modo, todos los objetos con los que se puede interactuar existentes pueden disfrutar de las ventajas de la nueva interacción en lugar de solo los que ha reescrito o ampliado.

XRControllers y enlace de entrada

La mayoría de los interactivos no se enlazan directamente a acciones de entrada. La mayoría deriva de XRBaseControllerInteractor, que requiere un objeto XRController superior al interactivo en la jerarquía. XRController enlaza con las acciones de entrada y luego propaga las acciones pertinentes (seleccionar, etc.) a todos los interactivos asociados.

Sin embargo, algunos interactivos pueden necesitar enlaces de entrada especiales o entrada adicional que XRController no proporciona. En estos casos, los interactivos tienen la opción de enlazar directamente a sus propias acciones de entrada únicas o incluso de usar otros orígenes que no son del sistema de entrada para la lógica de interacción. Las clases base de XRI prefieren escuchar a los enlaces de XRController, pero estos comportamientos se pueden invalidar para usar orígenes de entrada externos o alternativos.

Interfaces

XRI define las interfaces IXRInteractor, IXRHoverInteractor, IXRSelectInteractor e IXRActivateInteractor básicas. MRTK define interfaces adicionales para los interactivos. Algunas exponen información adicional sobre las interacciones específicas de MRTK, mientras que otras simplemente sobre la categorización y la identificación. Estas interfaces se encuentran en el paquete Core, mientras que las implementaciones residen en otros paquetes, incluido Input.

Importante

Aunque estas interfaces son útiles si se necesita filtrar por un tipo específico de interacción, se recomienda no codificar de forma rígida las interacciones para escuchar a estas interfaces específicamente. En cada situación, siempre dé preferencia a la interfaz genérica de XRI isSelected e isHovered en lugar de cualquier interfaz específica de la interacción.

A menos que sea absolutamente necesario, no debe hacer referencia a las implementaciones concretas de MRTK de estas interfaces en los objetos con los que se puede interactuar. En todos los casos, es mejor hacer referencia a las interfaces. Al hacer referencia explícitamente a los tipos concretos, se limita a los objetos con los que se puede interactuar a funcionar solo con los tipos actuales existentes. Al hacer referencia solo a las interfaces, se garantiza la compatibilidad con implementaciones futuras que pueden no aplicar subclases a las implementaciones existentes.

IVariableSelectInteractor

Los interactivos que implementan esta interfaz pueden emitir una selectividad variable (es decir, analógica) a los objetos con los que se puede interactuar. La cantidad de selectividad variable se puede consultar con la propiedad SelectProgress. Los interactivos de MRTK que implementan esta interfaz incluyen MRTKRayInteractor y GazePinchInteractor. Los objetos con los que se puede interactuar base (los objetos con los que se puede interactuar de XRI predeterminados y MRTKBaseInteractable) no se ven afectados por la cantidad de selectividad variable; StatefulInteractable, sin embargo, escucha a este valor y calcula su Selectedness en función del valor de max() de todos los interactivos variables y no variables participantes.

IGazeInteractor

Los interactivos que implementan esta interfaz representan la mirada pasiva del usuario, independiente de cualquier manipulación o intención. La implementación de MRTK es FuzzyGazeInteractor, que hereda de XRRayInteractor de XRI y agrega lógica aproximada de conversión de conos. XRBaseInteractable marca IsGazeHovered cuando se mantiene IGazeInteractor.

IGrabInteractor

Los interactivos que implementan esta interfaz representan una interacción física de agarre de campo cercano. attachTransform se define como el punto de agarre. La implementación de MRTK es GrabInteractor, que aplica subclases a XRDirectInteractor de XRI.

IPokeInteractor

Los interactivos que implementan esta interfaz representan una interacción de toque. Observe que esto no implica necesariamente un dedo. Los interactivos arbitrarios pueden implementar esta interfaz y ofrecer interacciones de toque de orígenes que no son dedos. En una de las pocas instancias en las que comprobar las interfaces del interactivo es una buena idea, objetos con los que se puede interactuar, como PressableButton, escuchan a IPokeInteractor, específicamente, para controlar la presión volumétrica. Cualquier interactivo que implemente IPokeInteractor induce presiones 3D en botones.

IPokeInteractor expone la propiedad PokeRadius, que define las características del objeto de toque. El toque se considera centrado en attachTransform y se extiende hacia fuera desde attachTransform mediante PokeRadius. Objetos con los que se puede interactuar, como PressableButton, desplazan su distancia de inserción 3D mediante este radio, que puede ser controlado por el grosor físico del dedo del usuario en el caso de las pulsaciones basadas en dedos.

La implementación de MRTK de esta interfaz es PokeInteractor. En nuestro proyecto de plantilla también se proporciona otro ejemplo de IPokeInteractor que no está controlado por el dedo; PenInteractor proporciona interacciones de toque basadas en la punta de un lápiz 3D virtual.

IRayInteractor

Los interactivos que implementan esta interfaz representan una interacción de apuntar basada en rayo. attachTransform representa la ubicación de impacto del rayo en la superficie del objeto de destino durante una selección.

La implementación de MRTK de esta interfaz es MRTKRayInteractor, que hereda directamente de XRRayInteractor de XRI.

Nota:

XRRayInteractor de XRI no implementa esta interfaz de MRTK.

ISpeechInteractor

Los interactivos que implementan esta interfaz representan interacciones controladas por voz. La implementación de MRTK es SpeechInteractor.

SpeechInteractor de MRTK, internamente, usa PhraseRecognitionSubsystem y se suscribe a eventos de registro de objetos con los que se puede interactuar de XRInteractionManager de XRI. Pero los objetos con los que se puede interactuar no deben preocuparse por qué subsistema está realizando el procesamiento de voz; ISpeechInteractor genera los mismos eventos de XRI (seleccionar, etc.) que cualquier otro interactivo.

IGazePinchInteractor

Esta interfaz es simplemente una especialización de la interfaz IVariableSelectInteractor. Los interactivos que implementan esta interfaz son, implícitamente, interactivos de selección de variables. IGazePinchInteractor representa expresamente una manipulación remota dirigida indirectamente. Un interactivo independiente basado en la mirada controla el destino de la interacción, y la manipulación es mediante una mano o un controlador. attachTransform se comporta de la misma manera que attachTransform de IRayInteractor; se ajusta al punto de impacto en el destino cuando se inicia una selección.

Cuando varios IGazePinchInteractor participan en una sola interacción, sus attachTransform se desplazan por su desplazamiento desde el punto medio entre todos los puntos de reducción participantes. Por lo tanto, los objetos con los que se puede interactuar pueden interpretar estos attachTransform de la misma manera que lo harían con cualquier otra interacción con varias manos, como attachTransforms de interacciones de agarre o las interacciones de rayo.

La implementación de MRTK es GazePinchInteractor.

IHandedInteractor

Algunos interactivos pueden optar por implementar la interfaz IHandedInteractor para especificar explícitamente que están asociados a una mano determinada en un usuario. Algunos interactivos no están asociados a la selección mediante la mano y, por tanto, no implementan esto. Los ejemplos más obvios serían SpeechInteractor o FuzzyGazeInteractor.

Los interactivos de MRTK que implementan esta interfaz son HandJointInteractor, un XRDirectInteractor genérico abstracto controlado por una asociación de mano arbitraria, GazePinchInteractor y MRTKRayInteractor.

Actualmente, los objetos con los que se puede interactuar usan esta interfaz para activar determinados efectos cuando se selecciona que deben eliminar la ambigüedad entre una mano izquierda o derecha. El ejemplo más notable es el efecto de pulso en la biblioteca de componentes de la experiencia del usuario.