Solucionadores: MRTK3
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. Ejemplo: colocación de un objeto en la superficie con la que se interseca el raycast de mirada del usuario.
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.
Cómo se usa
El sistema de solucionadores consta de tres categorías de scripts:
Solver
: Clase básica abstracta 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 cruza GameObject con las manos. Esto resulta útil en contenido interactivo restringido a mano, como menús, etc. Este solucionador está pensado para funcionar conXRNode
.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 controladoresXRNode
y se comportará igual que su clase base con otros tipos de controladores.Overlap
: se superpone al objeto con seguimiento.
Para usar el sistema de solucionadores, agregue uno de los componentes enumerados anteriormente a un elemento 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 simple SurfaceMagnetism
dará como resultado una proyección de rayo 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 o de controlador izquierdo y, luego, la derecha si la primera no está disponible o a menos que la propiedad TrackedHandedness
especifique lo contrario.
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 delante).
Para solucionar este problema, actualice la propiedad Rotación adicional en SolverHandler
a <90, 0, 0>. Esto garantizará que el vector que va hacia delante y que se ha suministrado a los solucionadores apunte a través de la palma y hacia fuera 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 elemento 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, las SolverHandler
llamadas GetComponents<Solver>()
al Inicio, devolverán los solucionadores en el orden en que aparecen en el inspector.
Además, al establecer la propiedad Updated Linked Transform en "true", se indicará que Solver
tiene que guardar su posición, orientación y escala calculadas en una variable intermedia accesible para 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 heredadas GoalPosition
, GoalRotation
y GoalScale
a los valores deseados. Además, es importante aprovechar SolverHandler.TransformTarget
como el fotograma de referencia que quiera el consumidor.
El código que se indica a continuación ofrece un ejemplo de un nuevo Componente de solucionador denominado InFront
que coloca el objeto adjunto 2 metros delante de SolverHandler.TransformTarget
. Si el consumidor establece el valor de SolverHandler.TrackedTargetType
como Head
, luego el elemento SolverHandler.TransformTarget
será la transformación de la cámara y, por tanto, este Solucionador situará el elemento GameObject adjunto a 2 metros 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 de GameObject.
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, 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.
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 determinan la cantidad de una parte de GameObject siempre debe estar en vista.
Las propiedades Min & Max Distance determinan cuánto se debe mantener el GameObject del usuario. Por ejemplo, si se avanza hacia el elemento GameObject con un valor de Min Distance (Distancia mínima) de 1 metro, el elemento GameObject se alejará para asegurarse de que nunca esté a menos de 1 metro del usuario.
Por lo general, RadialView
se usa junto con Tracked Target Type (Tipo de destino con seguimiento) establecido en Head
, de modo 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).
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 libremente (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 los grados máximos de vista horizontal y vertical y los mecanismos para modificar la orientación del objeto.
InBetween
La clase InBetween
mantendrá el GameObject adjunto entre dos transformaciones. El propio SolverHandler
tipo de destino con seguimiento de GameObject y la InBetween
propiedad Second Tracked Target Type del componente definen estos dos puntos de conexión de transformación. Por lo general, ambos tipos se establecerán en CustomOverride
y los valores SolverHandler.TransformOverride
y InBetween.SecondTransformOverride
se establecerán en los dos puntos de conexión con seguimiento.
El componente InBetween
creará otro componente SolverHandler
en el tiempo de ejecución 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 se colocará el objeto , a lo largo de la línea entre dos transformaciones; esto es, 0.5 corresponde a la mitad, 1.0 a la primera transformación y 0.0 a la segunda transformación.
SurfaceMagnetism
SurfaceMagnetism
funciona mediante la aplicación de un raycast frente a un LayerMask establecido de superficies y colocando el elemento 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.
Overlap
Overlap
es un solucionador sencillo que mantendrá la transformación del objeto en la misma posición y rotación que el destino de transformaciónSolverHandler's
.
Establecimiento de qué superficies se pueden impactar
Al agregar un componente SurfaceMagnetism
a un elemento GameObject, es importante tener en cuenta la capa del elemento GameObject y sus elementos secundarios, si es que alguno tiene colisionadores. El componente funciona mediante la aplicación de varios tipos de raycasts para determinar contra qué superficie se va a "imantar". Supongamos que el solucionador GameObject tiene un colisionador en una de las capas enumeradas en la propiedad MagneticSurfaces
de SurfaceMagnetism
. En ese caso, es probable que el raycast se alcance a sí mismo, lo que da lugar a que el elemento GameObject se adjunte a su propio punto de colisionador. Para evitar este comportamiento extraño, se puede establecer el elemento GameObject principal y todos los elementos secundarios en la capa Ignore Raycast (Omitir raycast) o modificar de forma correcta la matriz LayerMask MagneticSurfaces
.
Por el contrario, un elemento GameObject SurfaceMagnetism
no colisionará con las superficies de una capa que no aparezca en la propiedad MagneticSurfaces
. 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 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. Este punto viene determinado por la propiedad Directional Target.
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.
Factor de escala de visibilidad: Multiplicador para aumentar o disminuir el campo de visión que determina si el punto 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) y en la dirección del indicador, esta propiedad define lo lejos que está el objeto desde el centro de la ventanilla.
Escena de ejemplo de DirectionalIndicator (Assets/MRTK/Examples/Demos/Solvers/Scenes/DirectionalIndicatorSolverExample.unity)
Menú Mano con HandConstraint y HandConstraintPalmUp
El comportamiento HandConstraint
proporciona un solucionador que restringe el objeto de seguimiento a una región segura para el contenido restringido a mano (como la interfaz de usuario de mano, los menús, etc.). Las regiones seguras se consideran áreas que no se dividen con la mano. También se incluye una clase derivada HandConstraint
de 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 documentación Menú de mano para ver los ejemplos de uso del solucionador Hand Constraint para crear menús manuales.