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 CanvasProxyInteractor
de 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.