Punteros: MRTK2

Pointer

En este artículo se explica cómo configurar y responder a la entrada de puntero en la práctica. Para comprender mejor cómo controlar varios punteros en un nivel alto, consulte Arquitectura de puntero.

Los punteros se crean automáticamente en tiempo de ejecución cuando se detecta un nuevo controlador. Se puede conectar más de un puntero a un controlador. Por ejemplo, con el perfil de puntero predeterminado, Windows Mixed Reality controladores obtienen una línea y un puntero parabólico para la selección normal y la teletransporte respectivamente.

Configuración del puntero

Los punteros se configuran como parte del sistema de entrada en MRTK a través de .MixedRealityPointerProfile Este tipo de perfil se asigna a en MixedRealityInputSystemProfile el inspector de configuración de MRTK. El perfil de puntero determina el cursor, los tipos de punteros disponibles en tiempo de ejecución y cómo se comunican entre sí para decidir cuál está activo.

  • Extensión señalador : define la distancia máxima para la que un puntero puede interactuar con un GameObject.

  • Señalador máscaras de capa de Raycast : se trata de una matriz prioritaria de LayerMasks para determinar con qué posibles GameObjects puede interactuar cualquier puntero dado y el orden de interacción que se va a intentar. Esto puede ser útil para asegurarse de que los punteros interactúan primero con los elementos de la interfaz de usuario antes que otros objetos de escena. Pointer Profile Example

Configuración de opciones de puntero

La configuración predeterminada del perfil de puntero de MRTK incluye las siguientes clases de puntero y los objetos prefabricados asociados de fábrica. La lista de punteros disponibles para el sistema en tiempo de ejecución se define en Opciones de puntero en el perfil de puntero. Los desarrolladores pueden usar esta lista para volver a configurar los punteros existentes, agregar nuevos punteros o eliminar uno.

Pointer Options Profile Example

Cada entrada de puntero se define mediante el siguiente conjunto de datos:

  • Tipo de controlador: conjunto de controladores para los que un puntero es válido.

    • Por ejemplo, el PokePointer es responsable de los objetos "poking" con un dedo, y está marcado de forma predeterminada como solo compatible con el tipo de controlador de mano articulado. Solo se crean instancias de punteros cuando un controlador está disponible y, en particular, el tipo de controlador define con qué controladores se puede crear este objeto prefabricado de puntero.
  • Entrega : permite que solo se cree una instancia de un puntero para una mano específica (izquierda/derecha)

Nota

Si se establece la propiedad Handedness de una entrada pointer en None , se deshabilitará eficazmente desde el sistema como alternativa a quitar ese puntero de la lista.

  • Puntero Prefabricado : se creará una instancia de este recurso prefabricado cuando se inicie el seguimiento de un controlador que coincida con el tipo de controlador especificado y la entrega.

Es posible tener varios punteros asociados a un controlador. Por ejemplo, en DefaultHoloLens2InputSystemProfile (Assets/MRTK/SDK/Profiles/HoloLens2/) el controlador de mano articulado está asociado con PokePointer, GrabPointer y DefaultControllerPointer (es decir, rayos de mano).

Nota

MRTK proporciona un conjunto de objetos prefabricados de puntero en Assets/MRTK/SDK/Features/UX/Prefabs/Pointers. Se puede crear un nuevo objeto prefabricado personalizado siempre que contenga uno de los scripts de puntero en Assets/MRTK/SDK/Features/UX/Scripts/Pointers o cualquier otro script que implemente IMixedRealityPointer.

Configuración del cursor

El cursor De mirada se puede configurar directamente a través de la GazeCursorPrefab propiedad en dentro MixedRealityInputSystemProfile del Editor. Para configurar el cursor usado para otros punteros, debe cambiar el objeto prefabricado usado en el CursorPrefab campo del correspondiente BaseControllerPointer. Para cambiar el cursor mediante programación, modifique la BaseCursor propiedad en el comportamiento correspondiente IMixedRealityPointer .

Cursor Prefab Property

Consulte nuestros objetos prefabricados de cursor en Assets/MRTK/SDK/Features/UX/Prefabs/Cursors para ver implementaciones de comportamiento de cursor. En concreto, DefaultGazeCursor proporciona una implementación sólida de cambiar el gráfico del cursor en función del estado contextual.

Clases de puntero predeterminadas

Las siguientes clases son los punteros MRTK predefinidos disponibles y se definen en el perfil de puntero de MRTK predeterminado descrito anteriormente. Cada objeto prefabricado de puntero proporcionado en Assets/MRTK/SDK/Features/UX/Prefabs/Pointers contiene uno de los componentes de puntero asociados.

MRTK Default Pointers

Punteros lejanos

LinePointer

LinePointer, una clase de puntero base, dibuja una línea del origen de la entrada (es decir, el controlador) en la dirección del puntero y admite una única conversión de rayos en esta dirección. Por lo general, se crean instancias de clases secundarias como los ShellHandRayPointer punteros de teletransporte y se usan (que también dibujan líneas para indicar dónde terminará la teletransportación) en lugar de esta clase que proporciona principalmente funcionalidad común.

En el caso de los controladores de movimiento, como en Azure, Vive y Windows Mixed Reality, la rotación coincidirá con la rotación del controlador. Para otros controladores como HoloLens 2 manos articuladas, la rotación coincide con la posición apuntada proporcionada por el sistema de la mano.

MRTK Pointer Line
CurvePointer

CurvePointer extiende la clase LinePointer al permitir conversiones de rayos de varios pasos a lo largo de una curva. Esta clase de puntero base es útil para instancias curvadas, como punteros de teletransportación donde la línea se dobla de forma coherente en una parabola.

ShellHandRayPointer

La implementación de ShellHandRayPointer, que se extiende desde LinePointer, se usa como valor predeterminado para el perfil de puntero de MRTK. El objeto prefabricado DefaultControllerPointer implementa la ShellHandRayPointer clase .

GGVPointer

También conocido como puntero Mirada/Gesto/Voz (GGV), el GGVPointer potencia HoloLens apariencia de 1 estilo y pulsa las interacciones, principalmente a través de mirada y pulsación de aire o mirada y la interacción Select de voz. La posición y la dirección del puntero GGV están controladas por la posición y la rotación de la cabeza.

TouchPointer

TouchPointer es responsable de trabajar con la entrada Táctil de Unity (es decir, pantalla táctil). Estas son "interacciones lejanas" porque el acto de tocar la pantalla convertirá un rayo de la cámara en una ubicación potencialmente lejana en la escena.

MousePointer

El MousePointer alimenta una pantalla a raycast mundial para interacciones lejanas, pero para el mouse en lugar de tocar.

Mouse pointer

Nota

La compatibilidad con el mouse no está disponible de forma predeterminada en MRTK, pero se puede habilitar agregando un nuevo proveedor de datos de entrada de tipo MouseDeviceManager al perfil de entrada de MRTK y asignando al MixedRealityMouseInputProfile proveedor de datos.

Punteros cercanos

PokePointer

El PokePointer se usa para interactuar con objetos de juego que admiten "interacción casi táctil". que son GameObjects que tienen un script adjunto NearInteractionTouchable . En el caso de UnityUI, este puntero busca NearInteractionTouchableUnityUIs. El PokePointer usa sphereCast para determinar el elemento táctil más cercano y se usa para encender elementos como los botones presionables.

Al configurar gameObject con el NearInteractionTouchable componente , asegúrese de configurar el parámetro localForward para que apunte desde la parte frontal del botón u otro objeto que se debe hacer táctil. Asegúrese también de que los límites del táctil coincidan con los límites del objeto táctil.

Propiedades útiles de Poke Pointer:

  • TouchableDistance: distancia máxima en la que se puede interactuar con una superficie táctil
  • Objetos visuales: objeto game usado para representar el objeto visual de punta del dedo (el anillo en el dedo, de forma predeterminada).
  • Línea: línea opcional para dibujar desde el dedo hasta la superficie de entrada activa.
  • Máscaras de capa poke : una matriz prioritaria de LayerMasks para determinar con qué posibles Objetos GameObject el puntero puede interactuar con y el orden de interacción que se va a intentar. Ten en cuenta que un GameObject también debe tener un NearInteractionTouchable componente para interactuar con un puntero poke.
Poke Pointer
SpherePointer

SpherePointer usa UnityEngine.Physics.OverlapSphere para identificar el objeto más NearInteractionGrabbable cercano para la interacción, lo que resulta útil para la entrada "agarrable" como ManipulationHandler. Al igual que el PokePointer/NearInteractionTouchable par funcional, para poder interactuar con el puntero sphere, el objeto de juego debe contener un componente que sea el NearInteractionGrabbable script.

Grab Pointer

Propiedades útiles del puntero de esfera:

  • Radio de conversión de esfera: el radio de la esfera utilizada para consultar objetos que se pueden agarrar.
  • Margen de objeto cercano: distancia en la parte superior del radio de conversión de esfera que se va a consultar para detectar si un objeto está cerca del puntero. El radio total de detección de objetos cercanos es Radio de conversión de esfera + Margen de objeto cercano
  • Ángulo de sector del objeto cercano: ángulo alrededor del eje hacia delante del puntero para consultar objetos cercanos. Hace que la IsNearObject consulta funcione como un cono. Esto se establece en 66 grados de forma predeterminada para que coincida con el comportamiento de Hololens 2.

Sphere pointer modified to only query for objects in the forward direction

  • Factor de suavizado de objetos cercanos: factor de suavizado para la detección de objetos cercanos. Si se detecta un objeto en el radio de objeto cercano, el radio consultado se convierte en Radio de objeto cercano * (1 + Factor de suavizado de objetos cercanos) para reducir la sensibilidad y dificultar que un objeto deje el intervalo de detección.
  • Tomar máscaras de capa : una matriz prioritaria de LayerMasks para determinar con qué posibles Objetos GameObject el puntero puede interactuar con y el orden de interacción que se va a intentar. Ten en cuenta que un GameObject también debe tener un NearInteractionGrabbable para interactuar con un SpherePointer.

    Nota

    La capa de reconocimiento espacial está deshabilitada en el objeto prefabricado GrabPointer predeterminado proporcionado por MRTK. Esto se hace para reducir el impacto en el rendimiento de realizar una consulta de superposición de esfera con la malla espacial. Puede habilitarlo modificando el objeto prefabricado GrabPointer.

  • Omitir colisionadores no en FOV : si se omiten los colisionadores que pueden estar cerca del puntero, pero no realmente en el FOV visual. Esto puede evitar agarres accidentales, y permitirá que los rayos de mano se activen cuando pueda estar cerca de un agarrable, pero no pueden verlo. El FOV visual se define a través de un cono en lugar del frustum típico por motivos de rendimiento. Este cono está centrado y orientado al mismo que el frustum de la cámara con un radio igual a la mitad de la altura de la pantalla (o FOV vertical).
Sphere Pointer

Punteros de teletransporte

  • TeleportPointer generará una solicitud de teletransporte cuando se realiza una acción (es decir, se presiona el botón de teletransporte) para mover el usuario.
  • ParabolicTeleportPointer generará una solicitud de teletransporte cuando se realiza una acción (es decir, se presiona el botón de teletransporte) con un raycast de línea parabólica para mover al usuario.
Pointer Parabolic

Compatibilidad con punteros para plataformas de realidad mixta

En la tabla siguiente se detallan los tipos de puntero que se usan normalmente para las plataformas comunes de MRTK. NOTA: Es posible agregar diferentes tipos de puntero a estas plataformas. Por ejemplo, podrías agregar un puntero Poke o un puntero sphere a VR. Además, los dispositivos VR con un controlador para juegos podrían usar el puntero GGV.

Puntero OpenVR Windows Mixed Reality HoloLens 1 HoloLens 2
ShellHandRayPointer Válido Válido Válido
TeleportPointer Válido Válido
GGVPointer Válido
SpherePointer Válido
PokePointer Válido

Interacciones de puntero a través del código

Interfaces de eventos de puntero

MonoBehaviours que implementan una o varias de las siguientes interfaces y se asignan a un GameObject con un Collider recibirá eventos de interacciones de puntero según lo definido por la interfaz asociada.

Evento Descripción Controlador
Antes de cambiar el foco o cambiar el foco Se genera tanto en el objeto de juego que pierde el foco como en el que lo gana cada vez que un puntero cambia el foco. IMixedRealityFocusChangedHandler
Entrada y salida del foco Elevado en el objeto del juego ganando foco cuando el primer puntero entra en él y en el que pierde el foco cuando el último puntero lo deja. IMixedRealityFocusHandler
Puntero hacia abajo/Arrastrado/Hacia arriba/Clic Se genera para informar de la presión del puntero, arrastre y suelte. IMixedRealityPointerHandler
Touch Started/Updated/Completed Se genera mediante punteros táctiles como PokePointer para informar de la actividad táctil. IMixedRealityTouchHandler

Nota

IMixedRealityFocusChangedHandler y IMixedRealityFocusHandler deben controlarse en los objetos en los que se generan. Es posible recibir eventos de foco globalmente, pero, a diferencia de otros eventos de entrada, el controlador de eventos globales no bloqueará la recepción de eventos en función del foco (el controlador global recibirá el evento y un objeto correspondiente en el foco).

Eventos de entrada de puntero en acción

El sistema de entrada de MRTK reconoce y controla los eventos de entrada de puntero de forma similar a los eventos de entrada normales. La diferencia es que los eventos de entrada de puntero solo los controla GameObject en el foco mediante el puntero que ha desencadenado el evento de entrada, así como cualquier controlador de entrada global. Los eventos de entrada normales se controlan mediante GameObjects en el foco para todos los punteros activos.

  1. El sistema de entrada de MRTK reconoce que se ha producido un evento de entrada
  2. El sistema de entrada MRTK activa la función de interfaz pertinente para el evento de entrada a todos los controladores de entrada globales registrados.
  3. El sistema de entrada determina qué GameObject está enfocado para el puntero que desencadenó el evento.
    1. El sistema de entrada utiliza el sistema de eventos de Unity para activar la función de interfaz pertinente para todos los componentes coincidentes en el GameObject centrado.
    2. Si en cualquier momento un evento de entrada se ha marcado como usado, el proceso finalizará y ningún gameObjects recibirá devoluciones de llamada.
      • Ejemplo: Los componentes que implementan la interfaz IMixedRealityFocusHandler se buscarán ganancias o pérdida de foco de GameObject.
      • Nota: El sistema de eventos de Unity se propagará hasta buscar el GameObject primario si no se encuentra ningún componente que coincida con la interfaz deseada en el gameObject actual.
  4. Si no se registran controladores de entrada globales y no se encuentra gameObject con un componente o interfaz coincidente, el sistema de entrada llamará a cada controlador de entrada registrado de reserva.

Ejemplo

A continuación se muestra un script de ejemplo que cambia el color del representador adjunto cuando un puntero toma o deja el foco o cuando un puntero selecciona el objeto.

public class ColorTap : MonoBehaviour, IMixedRealityFocusHandler, IMixedRealityPointerHandler
{
    private Color color_IdleState = Color.cyan;
    private Color color_OnHover = Color.white;
    private Color color_OnSelect = Color.blue;
    private Material material;

    private void Awake()
    {
        material = GetComponent<Renderer>().material;
    }

    void IMixedRealityFocusHandler.OnFocusEnter(FocusEventData eventData)
    {
        material.color = color_OnHover;
    }

    void IMixedRealityFocusHandler.OnFocusExit(FocusEventData eventData)
    {
        material.color = color_IdleState;
    }

    void IMixedRealityPointerHandler.OnPointerDown(
         MixedRealityPointerEventData eventData) { }

    void IMixedRealityPointerHandler.OnPointerDragged(
         MixedRealityPointerEventData eventData) { }

    void IMixedRealityPointerHandler.OnPointerClicked(MixedRealityPointerEventData eventData)
    {
        material.color = color_OnSelect;
    }
}

Punteros de consulta

Es posible recopilar todos los punteros activos actualmente mediante el bucle de los orígenes de entrada disponibles (es decir, controladores y entradas disponibles) para detectar qué punteros están conectados a ellos.

var pointers = new HashSet<IMixedRealityPointer>();

// Find all valid pointers
foreach (var inputSource in CoreServices.InputSystem.DetectedInputSources)
{
    foreach (var pointer in inputSource.Pointers)
    {
        if (pointer.IsInteractionEnabled && !pointers.Contains(pointer))
        {
            pointers.Add(pointer);
        }
    }
}

Puntero principal

Los desarrolladores pueden suscribirse al evento FocusProviders PrimaryPointerChanged para recibir una notificación cuando el puntero principal en el foco ha cambiado. Esto puede ser muy útil para identificar si el usuario está interactuando actualmente con una escena a través de una mirada o un rayo de mano u otro origen de entrada.

private void OnEnable()
{
    var focusProvider = CoreServices.InputSystem?.FocusProvider;
    focusProvider?.SubscribeToPrimaryPointerChanged(OnPrimaryPointerChanged, true);
}

private void OnPrimaryPointerChanged(IMixedRealityPointer oldPointer, IMixedRealityPointer newPointer)
{
    ...
}

private void OnDisable()
{
    var focusProvider = CoreServices.InputSystem?.FocusProvider;
    focusProvider?.UnsubscribeFromPrimaryPointerChanged(OnPrimaryPointerChanged);

    // This flushes out the current primary pointer
    OnPrimaryPointerChanged(null, null);
}

La PrimaryPointerExample escena (Assets/MRTK/Examples/Demos/Input/Scenes/PrimaryPointer) muestra cómo usar para PrimaryPointerChangedHandler que los eventos respondan a un nuevo puntero principal.

Primary Pointer Example

Resultado del puntero

La propiedad de puntero Result contiene el resultado actual de la consulta de escena utilizada para determinar el objeto con foco. Para un puntero de raycast, como los creados de forma predeterminada para los controladores de movimiento, la entrada de mirada y los rayos de mano, contendrá la ubicación y la normalidad del golpe de raycast.

private void IMixedRealityPointerHandler.OnPointerClicked(MixedRealityPointerEventData eventData)
{
    var result = eventData.Pointer.Result;
    var spawnPosition = result.Details.Point;
    var spawnRotation = Quaternion.LookRotation(result.Details.Normal);
    Instantiate(MyPrefab, spawnPosition, spawnRotation);
}

La PointerResultExample escena (Assets/MRTK/Examples/Demos/Input/Scenes/PointerResult/PointerResultExample.unity) muestra cómo usar el puntero Result para generar un objeto en la ubicación de aciertos.

Pointer Result

Deshabilitar punteros

Para activar y deshabilitar punteros (por ejemplo, para deshabilitar el rayo de mano), establezca para PointerBehavior un tipo de puntero determinado a través de PointerUtils.

// Disable the hand rays
PointerUtils.SetHandRayPointerBehavior(PointerBehavior.AlwaysOff);

// Disable hand rays for the right hand only
PointerUtils.SetHandRayPointerBehavior(PointerBehavior.AlwaysOff, Handedness.Right);

// Disable the gaze pointer
PointerUtils.SetGazePointerBehavior(PointerBehavior.AlwaysOff);

// Set the behavior to match HoloLens 1
// Note, if on HoloLens 2, you must configure your pointer profile to make the GGV pointer show up for articulated hands.
public void SetHoloLens1()
{
    PointerUtils.SetPokePointerBehavior(PointerBehavior.AlwaysOff, Handedness.Any);
    PointerUtils.SetGrabPointerBehavior(PointerBehavior.AlwaysOff, Handedness.Any);
    PointerUtils.SetRayPointerBehavior(PointerBehavior.AlwaysOff, Handedness.Any);
    PointerUtils.SetGGVBehavior(PointerBehavior.Default);
}

Consulte PointerUtils y TurnPointersOnOff para obtener más ejemplos.

Interacciones de puntero a través del editor

En el caso de los eventos de puntero controlados por IMixedRealityPointerHandler, MRTK proporciona mayor comodidad en forma de PointerHandler componente, lo que permite que los eventos de puntero se controlen directamente a través de eventos de Unity.

Pointer Handler

Extensión del puntero

Los punteros lejanos tienen una configuración que limita la distancia a la que se van a raycastar e interactuar con otros objetos de la escena. De forma predeterminada, este valor se establece en 10 metros. Este valor se eligió para mantener la coherencia con el comportamiento del shell de HoloLens.

Esto se puede cambiar actualizando los DefaultControllerPointer campos del ShellHandRayPointer componente prefabricado:

Extensión del puntero : controla la distancia máxima con la que interactuarán los punteros.

Extensión de puntero predeterminada : controla la longitud del rayo o línea de puntero que se representará cuando el puntero no interactúe con nada.

Consulta también