Introducción al solucionador: MRTK2
Los solucionadores son componentes que facilitan los medios para calcular la posición y la orientación de un objeto según un algoritmo predefinido. Un ejemplo puede ser la colocación de un objeto en la superficie donde golpea actualmente el raycast de la mirada del usuario.
Además, el sistema de solucionadores define de manera determinista un orden de operaciones para estos cálculos de transformación, ya que no hay ninguna manera confiable de especificar a Unity el orden de actualización de los componentes.
Los solucionadores ofrecen una variedad de comportamientos para adjuntar objetos a otros objetos o sistemas. Otro ejemplo sería un objeto con etiquetas continuas que mantiene el puntero delante del usuario (en función de la cámara). También se puede adjuntar un solucionador a un controlador y un objeto para que el objeto etiquete el controlador de manera continua. Todos los solucionadores se pueden apilar de manera segura, por ejemplo, un comportamiento de etiquetas continuas + magnetismo de superficie + impulso.
Procedimiento para usar un solucionador
El sistema de solucionadores consta de tres categorías de scripts:
Solver
: Clase abstracta base de la que derivan todos los solucionadores. Ofrece seguimiento del estado, parámetros de suavizado e implementación, integración automática del sistema de solucionadores y orden de actualización.SolverHandler
: Establece el objeto de referencia con el que se realiza el seguimiento (por ejemplo, la transformación de la cámara principal, el haz de mano, etc.), controla la recopilación de componentes de los solucionadores y ejecuta la actualización en el orden correcto.
La tercera categoría es el solucionador mismo. Los siguientes solucionadores brindan los bloques de creación para el comportamiento básico:
Orbital
: Se bloquea en una posición y desplazamiento especificados con respecto al objeto referenciado.ConstantViewSize
: Escala para mantener un tamaño constante con respecto a la vista del objeto referenciado.RadialView
: Mantiene el objeto dentro de una proyección cónica de vista por el objeto referenciado.Follow
: Mantiene el objeto dentro de un conjunto de límites del objeto referenciado definidos por el usuario.InBetween
: Mantiene un objeto entre dos objetos a los que se hace un seguimiento.SurfaceMagnetism
: Proyecta rayos en las superficies del mundo y alinea el objeto con esa superficie.DirectionalIndicator
: Establece la posición y la orientación de un objeto como indicador direccional. Desde el punto de la referencia del destino de seguimiento de SolverHandler, este indicador se orientará hacia el directionalTarget señalado.Momentum
: Aplica aceleración, velocidad o fricción para simular el impulso y la elasticidad de un objeto que es movido por otros solucionadores o componentes.HandConstraint
: Restringe el objeto para que siga las manos en una región que no interseca GameObject con las manos. Resulta útil para contenido interactivo restringido a mano, como menús, etc. Este solucionador está pensado para funcionar con IMixedRealityHand, pero también funciona con IMixedRealityController.HandConstraintPalmUp
: Proviene de HandConstraint, pero incluye lógica para probar si la palma está orientada hacia el usuario antes de la activación. Este solucionador solo funciona con controladores IMixedRealityHand; con otros tipos de controlador, este solucionador se comportará igual que su clase base.
Para usar el sistema de solucionadores, simplemente agregue uno de los componentes enumerados anteriormente a un GameObject. Dado que todos los solucionadores requieren una clase SolverHandler
, Unity creará una automáticamente.
Nota:
Puede encontrar ejemplos de cómo usar el sistema de solucionadores en el archivo SolverExamples.scene.
Procedimiento para cambiar la referencia de seguimiento
La propiedad Tipo de destino de seguimiento del componente SolverHandler
define el punto de referencia que todos los solucionadores usarán para calcular sus algoritmos. Por ejemplo, un tipo de valor de Head
con un componente SurfaceMagnetism
simple dará como resultado un raycast desde la cabeza y en la dirección de la mirada del usuario para resolver qué superficie alcanza. Los valores potenciales para la propiedad TrackedTargetType
son:
- Head: El punto de referencia es la transformación de la cámara principal.
- ControllerRay: el punto de referencia es la
LinePointer
transformación en un controlador (es decir, el origen del puntero en un controlador de movimiento o controlador de mano) que apunta en la dirección del rayo de línea.- Use la propiedad
TrackedHandedness
para seleccionar la preferencia de diestro o zurdo (es decir, izquierda, derecha o ambas).
- Use la propiedad
- HandJoint: El punto de referencia es la transformación de una articulación manual específica
- Use la propiedad
TrackedHandedness
para seleccionar la preferencia de diestro o zurdo (es decir, izquierda, derecha o ambas). - Use la propiedad
TrackedHandJoint
para determinar la transformación de la articulación que se usará.
- Use la propiedad
- CustomOverride: Punto de referencia de la
TransformOverride
asignada.
Nota:
Para los tipos ControllerRay y HandJoint, el controlador del solucionador intentará proporcionar primero la transformación de mano/controlador izquierdo y, luego, la derecha si la primera no está disponible o a menos que la propiedad TrackedHandedness
especifique lo contrario.
Ejemplo de varias propiedades asociadas a cada TrackedTargetType
Importante
La mayoría de los solucionadores usan el vector hacia delante del destino de transformación con seguimiento proporcionado por SolverHandler
. Cuando se usa un tipo de destino con seguimiento de HandJoint, el vector hacia delante de la articulación de la mano puede apuntar a través de los dedos y no a través de la palma. Esto depende de la plataforma que suministra los datos de la articulación de la mano. En el caso de la simulación de entrada y Windows Mixed Reality, es el vector ascendente el que apunta hacia arriba a través de la palma (es decir, el vector verde hacia arriba, el vector azul hacia adelante).
Para solucionar este problema, actualice la propiedad Rotación adicional en SolverHandler
a <90, 0, 0>. Esto garantizará que el vector hacia delante proporcionado a los solucionadores apunte a través de la palma y alejándose de la mano.
Como alternativa, use el tipo de destino con seguimiento Controller Ray (Rayo del controlador) para obtener un comportamiento similar para apuntar con las manos.
Procedimiento para encadenar solucionadores
Es posible agregar varios componentes Solver
al mismo GameObject, con lo que sus algoritmos se encadenan. El componente SolverHandler
controla la actualización de todos los solucionadores en el mismo GameObject. De manera predeterminada, SolverHandler
llama a GetComponents<Solver>()
en el inicio, lo que devolverá los solucionadores en el orden en que aparecen en el inspector.
Además, establecer la propiedad Transformación vinculada actualizada en true indicará que Solver
guarde su posición calculada, orientación y escala en una variable intermedia accesible por todos los solucionadores (es decir GoalPosition
, ). Cuando se establece en false (falso), Solver
actualizará la transformación de GameObject directamente. Al guardar las propiedades de la transformación en una ubicación intermediaria, otros solucionadores pueden realizar sus cálculos a partir de la variable intermediaria. Esto se debe a que Unity no permite que las actualizaciones de gameObject.transform se apilen dentro del mismo fotograma.
Nota:
Para modificar el orden de ejecución de los solucionadores, los desarrolladores pueden establecer la propiedad SolverHandler.Solvers
directamente.
Procedimiento para crear un nuevo solucionador
Todos los solucionadores deben heredar de la clase base abstracta, Solver
. Los requisitos principales de una extensión de solucionador implican invalidar el método SolverUpdate
. En este método, los desarrolladores deben actualizar las propiedades GoalPosition
, GoalRotation
y GoalScale
heredadas a los valores deseados. Además, suele ser útil aprovechar SolverHandler.TransformTarget
como fotograma de referencia deseado por el consumidor.
El código que se brinda a continuación ofrece un ejemplo de un nuevo componente de solucionador denominado InFront
que coloca el objeto adjunto 2 m delante de SolverHandler.TransformTarget
. Si el consumidor establece el valor de SolverHandler.TrackedTargetType
como Head
, SolverHandler.TransformTarget
será la transformación de la cámara y, por tanto, este solucionador colocará el GameObject adjunto 2 m delante de la mirada de los usuarios en cada fotograma.
/// <summary>
/// InFront solver positions an object 2m in front of the tracked transform target
/// </summary>
public class InFront : Solver
{
...
public override void SolverUpdate()
{
if (SolverHandler != null && SolverHandler.TransformTarget != null)
{
var target = SolverHandler.TransformTarget;
GoalPosition = target.position + target.forward * 2.0f;
}
}
}
Guías de implementación de solucionadores
Propiedades comunes de los solucionadores
Cada componente del solucionador tiene un conjunto básico de propiedades idénticas que controlan el comportamiento principal del solucionador.
Si Smoothing está habilitado, el solucionador actualizará gradualmente la transformación de GameObject con el tiempo a los valores calculados. La velocidad de este cambio viene determinada por la propiedad LerpTime de cada componente de transformación. Por ejemplo, un valor MoveLerpTime mayor generará incrementos más lentos en el movimiento entre fotogramas.
Si MaintainScale está habilitado, el solucionador usará la escala local predeterminada del GameObject.
Propiedades comunes heredadas por todos los componentes de los solucionadores
Orbital
La clase Orbital
es un componente de etiquetas continuas que se comporta como los planetas en un sistema solar. Este solucionador garantizará que los GameObject adjuntos orbiten alrededor de la transformación a la que se hace el seguimiento. Por lo tanto, si Tracked Target Type (Tipo de destino con seguimiento) de SolverHandler
está establecido en Head
, el GameObject orbitará alrededor de la cabeza del usuario con la aplicación de un desplazamiento fijo.
Los desarrolladores pueden modificar este desplazamiento fijo para mantener los menús u otros componentes de la escena en el nivel ocular o de la cintura, etc., en torno a un usuario. Para ello, modifique las propiedades Local Offset (Desplazamiento local) y World Offset (Desplazamiento del mundo). La propiedad Orientation Type (Tipo de orientación) determina la rotación que se aplica al objeto si debe mantener su rotación original, o estar siempre frente a la cámara o frente a cualquier transformación que impulse su posición, etc.
Ejemplo de Orbital
RadialView
RadialView
es otro componente de etiquetas continuas que mantiene una parte determinada de un GameObject dentro del tronco de la vista del usuario.
Las propiedades Min/Max View Degrees (Mín. y Máx. de grados de visión) determinan el tamaño de una parte del GameObject que siempre debe estar a la vista.
Las propiedades Min/Max View Degrees (Mín. y Máx. de grados de visión) determinan hasta qué punto se debe mantener alejado el GameObject del usuario. Por ejemplo, si se avanza hacia el GameObject con Min Distance (Distancia mínima) de 1 m, el GameObject se alejará para asegurarse de que nunca esté a menos de 1 m del usuario.
Por lo general, RadialView
se usa junto con Tracked Target Type (Tipo de destino con seguimiento) establecido en Head
para que el componente siga la mirada del usuario. Sin embargo, este componente puede funcionar para mantenerse en la "vista" de cualquier Tracked Target Type (Tipo de destino con seguimiento).
Ejemplo de RadialView
Seguir
La clase Follow
coloca un elemento delante del destino al que se hace el seguimiento en relación con su eje de avance local. El elemento se puede restringir de forma flexible (también conocido como etiquetado) para que no siga hasta que el destino del que se realiza el seguimiento se mueva más allá de los límites definidos por el usuario.
Funciona de forma similar al solucionador RadialView, con controles adicionales para administrar Max Horizontal/Vertical View Degrees (Máx. de grados de visión horizontal y vertical), y mecanismos para modificar Orientation (Orientación) del objeto.
Propiedades de seguimiento
Escena de ejemplo de Follow (Assets/MRTK/Examples/Demos/Solvers/Scenes/FollowSolverExample.unity)
InBetween
La clase InBetween
mantendrá el GameObject adjunto entre dos transformaciones. Estos dos puntos de transformación se definen mediante Tracked Target Type (Tipo de destino con seguimiento) del propio SolverHandler
del GameObject, y la propiedad Second Tracked Target Type (Segundo tipo de destino con seguimiento) del componente InBetween
. Por lo general, ambos tipos se establecerán en CustomOverride
, y los valores SolverHandler.TransformOverride
y InBetween.SecondTransformOverride
resultantes se establecerán en los dos puntos con seguimiento.
En tiempo de ejecución, el componente InBetween
creará otro componente SolverHandler
según las propiedades Second Tracked Target Type (Segundo tipo de destino con seguimiento) y Second Transform Override (Segunda invalidación de transformación).
PartwayOffset
define dónde, a lo largo de la línea entre dos transformaciones, se colocará el objeto; donde 0,5 es la mitad, 1,0 en la primera transformación, y 0,0 en la segunda transformación.
Ejemplo de uso del solucionador InBetween para mantener el objeto entre dos transformaciones
SurfaceMagnetism
SurfaceMagnetism
funciona mediante la aplicación de un raycast frente a un LayerMask establecido de superficies y colocando el GameObject en ese punto de contacto.
Surface Normal Offset (Desplazamiento normal de la superficie) colocará el GameObject a una distancia establecida en metros de distancia de la superficie en la dirección de la normal en el punto de impacto en la superficie.
Por el contrario, Surface Ray Offset (Desplazamiento del rayo en la superficie) colocará el Objeto GameObject a una distancia establecida en metros de la superficie, pero en la dirección opuesta del raycast aplicado. Por lo tanto, si el raycast es la mirada del usuario, el GameObject se acercará a lo largo de la línea desde el punto de impacto en la superficie hasta la cámara.
Orientation Mode (Modo de orientación) determina el tipo de rotación que se aplicará en relación con la normal en la superficie.
- None: No se aplica ninguna rotación.
- TrackedTarget: El objeto se enfrentará a la transformación con seguimiento que controla el raycast.
- SurfaceNormal: El objeto se alineará en función de la normal en el punto de impacto en la superficie.
- Blended: El objeto se alineará en función de la normal en el punto de impacto en la superficie, y en función de la orientación de la transformación con seguimiento.
Para forzar que el Objeto GameObject asociado permanezca vertical en cualquier modo distinto de None, habilite Keep Orientation Vertical (Mantener orientación vertical).
Nota:
Use la propiedad Orientation Blend (Combinación de orientación) para controlar el equilibrio entre los factores de rotación Orientation Mode (Modo de orientación) está establecido en Blended. Con un valor de 0,0, la orientación se controlará completamente con el modo TrackedTarget; y con un valor de 1,0, la orientación se controlará completamente con SurfaceNormal.
Establecimiento de qué superficies se pueden impactar
Al agregar un componente SurfaceMagnetism
a un GameObject, es importante tener en cuenta la capa del GameObject y sus elementos secundarios, si alguno tiene colisionadores. El componente funciona mediante la aplicación de varios tipos de raycasts para determinar con qué superficie se va a "imantar". Si el GameObject del solucionador tiene un colisionador en una de las capas enumeradas en la propiedad MagneticSurfaces
de SurfaceMagnetism
, es probable que el raycast se alcance a sí mismo, lo que dará lugar a que el GameObject se adjunte a su propio punto de colisión. Para evitar este comportamiento extraño, se puede establecer el GameObject principal y todos los elementos secundarios en la capa Ignore Raycast (Omitir raycast) o modificar correctamente la matriz LayerMask de MagneticSurfaces
.
Por el contrario, un GameObject de SurfaceMagnetism
no colisionará con las superficies de una capa que no aparezca en la propiedad MagneticSurfaces
. Por lo general, se recomienda colocar todas las superficies deseadas en una capa dedicada (es decir, Superficies) y configurar la propiedad MagneticSurfaces
solo para esta capa. El uso de default o everything puede dar lugar a que los componentes de la interfaz de usuario o los cursores contribuyan al solucionador.
Por último, los raycasts de SurfaceMagnetism
omitirán las superficies más alejadas de la configuración de la propiedad MaxRaycastDistance
.
DirectionalIndicator
La clase DirectionalIndicator
es un componente de etiquetas continuas que se orienta a sí mismo a la dirección de un punto deseado en el espacio.
Se usa normalmente cuando Tracked Target Type (Tipo de destino con seguimiento) de SolverHandler
se establece en Head
. De este modo, un componente de la experiencia de usuario con el solucionador DirectionalIndicator
dirigirá a un usuario a que mire el punto deseado en el espacio.
El punto deseado en el espacio se determina a través de la propiedad Directional Target (Destino direccional).
Si el usuario puede ver el destino direccional, o cualquier fotograma de referencia se establece en SolverHandler
, este solucionador deshabilitará todos los componentes Renderer
debajo de él. Si no se puede ver, todo se habilitará en el indicador.
El tamaño del indicador se reducirá cuanto más se acerque el usuario a capturar el valor de Directional Target (Destino direccional) en su campo de visión.
Min Indicator Scale (Escala mínima del indicador): Escala mínima para el objeto indicador.
Max Indicator Scale (Escala máxima del indicador): Escala máxima para el objeto indicador.
Visibility Scale Factor (Factor de escala de visibilidad): Multiplicador para aumentar o disminuir el campo de visión que determina si el punto Directional Target (Destino direccional) se puede ver o no.
Desplazamiento de vista: desde el punto de vista del marco de referencia (es decir, posiblemente la cámara), esta propiedad define hasta qué punto en la dirección del indicador debe estar el objeto desde el centro de la ventanilla.
Propiedades del indicador direccional
Escena de ejemplo de DirectionalIndicator (Assets/MRTK/Examples/Demos/Solvers/Scenes/DirectionalIndicatorSolverExample.unity)
Menú Mano con HandConstraint y HandConstraintPalmUp
El comportamiento de HandConstraint
proporciona un solucionador que restringe el objeto con seguimiento a una región segura para el contenido restringido a la mano (como la interfaz de usuario de la mano, los menús, etc.). Las regiones seguras se consideran áreas que no se intersecan con la mano. También se incluye una clase derivada de HandConstraint
llamada HandConstraintPalmUp
para mostrar un comportamiento común de activar el objeto con seguimiento del solucionador cuando la palma mira hacia el usuario.
Consulte la página Menú Mano para ver los ejemplos de uso del solucionador HandConstraint para crear menús de mano.