Seleção de destino com suporte ocular – MRTK2

MRTK

Esta página discute diferentes opções para acessar dados de foco ocular e eventos específicos do olhar para selecionar destinos no MRTK. O acompanhamento ocular permite seleções de destino rápidas e sem esforço usando uma combinação de informações sobre o que um usuário está olhando com entradas adicionais, como controle manual e comandos de voz:

  • Look & Say "Select" (comando de voz padrão)
  • Look & Say "Explode" ou "Pop" (comandos de voz personalizados)
  • Botão Procurar & Bluetooth
  • Look & Pinch (ou seja, segure a mão na sua frente e coloque o polegar e o dedo indicador juntos)

Para selecionar o conteúdo holográfico usando o olhar, há várias opções:

1. Use o ponteiro de foco primário:

Isso pode ser entendido como seu cursor priorizado. Por padrão, se as mãos estiverem em exibição, isso seria raios de mão. Se nenhuma mão estiver em exibição, o ponteiro priorizado será o olhar ou a cabeça. Portanto, observe que, com base no foco de design atual ou no olhar ocular, é suprimido como uma entrada de cursor se os raios manuais forem usados.

Por exemplo:

Um usuário deseja selecionar um botão holográfico distante. Como desenvolvedor, você deseja fornecer uma solução flexível que permita que o usuário alcance essas tarefas em várias condições:

  • Ande até o botão e cutuque-o
  • Olhe para ele à distância e diga "selecionar"
  • Direcione o botão usando um raio manual e executando uma pitada Nesse caso, a solução mais flexível é usar o manipulador de foco primário, pois ele notificará você sempre que o ponteiro de foco primário atualmente priorizado disparar um evento. Observe que, se os raios manuais estiverem habilitados, o ponteiro de foco da cabeça ou do olhar será desabilitado assim que as mãos entrarem em exibição.

Importante

Observe que, se os raios manuais estiverem habilitados, o ponteiro de foco da cabeça ou do olhar será desabilitado assim que as mãos entrarem em exibição. Se você quiser dar suporte a uma interação de "olhar e beliscar", será necessário desabilitar o raio de mão. Em nossas cenas de exemplo de acompanhamento ocular, desabilitamos o raio de mão para permitir a exibição de interações mais avançadas usando olhos + movimentos de mão - veja, por exemplo , Posicionamento Com Suporte para Olhos.

2. Use o foco ocular e os raios manuais ao mesmo tempo:

Pode haver instâncias em que você deseja ser mais específico que tipo de ponteiros de foco podem disparar determinados eventos e permitir o uso simultâneo de várias técnicas de interação distante.

Por exemplo: em seu aplicativo, um usuário pode usar raios de mão distantes para manipular alguma instalação mecânica holográfica - por exemplo, pegar e segurar algumas partes distantes do mecanismo holográfico e mantê-las no lugar. Ao fazer isso, o usuário precisa passar por várias instruções e registrar seu progresso marcando algumas caixas de seleção. Se o usuário não tiver as mãos ocupadas, seria instintivo simplesmente tocar na caixa de seleção ou selecioná-la usando um raio de mão. No entanto, se o usuário tiver as mãos ocupadas, como em nosso caso, segurando algumas partes do mecanismo holográfico no local, você deseja permitir que o usuário role diretamente as instruções usando o olhar e simplesmente olhe para uma caixa de seleção e diga "verifique!".

Para habilitar isso, você precisa usar o script EyeTrackingTarget específico para os olhos que é independente dos principais FocusHandlers do MRTK e será discutido mais abaixo.

1. Usar manipuladores genéricos de foco e ponteiro

Se o acompanhamento ocular estiver configurado corretamente (consulte a configuração básica do MRTK para usar o acompanhamento ocular), permitir que os usuários selecionem hologramas usando seus olhos é o mesmo que para qualquer outra entrada de foco (por exemplo, olhar para a cabeça ou raio manual). Isso oferece a grande vantagem de uma maneira flexível de interagir com seus hologramas definindo o tipo de foco principal em seu Perfil de Ponteiro de Entrada MRTK, dependendo das necessidades do usuário, deixando seu código intocado. Isso permite alternar entre a cabeça ou o olhar sem alterar uma linha de código ou substituir raios manuais por direcionamento ocular para interações distantes.

Focando em um holograma

Para detectar quando um holograma está focado, use a interface 'IMixedRealityFocusHandler' que fornece dois membros da interface: OnFocusEnter e OnFocusExit.

Aqui está um exemplo simples de ColorTap.cs para alterar a cor de um holograma ao ser examinado.

public class ColorTap : MonoBehaviour, IMixedRealityFocusHandler
{
    void IMixedRealityFocusHandler.OnFocusEnter(FocusEventData eventData)
    {
        material.color = color_OnHover;
    }

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

Selecionando um holograma focado

Para selecionar um holograma focado, use PointerHandler para escutar eventos de entrada para confirmar uma seleção. Por exemplo, adicionar o IMixedRealityPointerHandler os fará reagir à entrada de ponteiro simples. A interface IMixedRealityPointerHandler requer a implementação dos três membros da interface a seguir: OnPointerUp, OnPointerDown e OnPointerClicked.

No exemplo abaixo, alteramos a cor de um holograma olhando para ele e beliscando ou dizendo "selecionar". A ação necessária para disparar o evento é definida pelo eventData.MixedRealityInputAction == selectAction qual podemos definir o tipo do selectAction Editor do Unity – por padrão, é a ação "Selecionar". Os tipos de MixedRealityInputActions disponíveis podem ser configurados no Perfil MRTK por meio do Perfil de Configuração do MRTK ->Input ->Input Actions.

public class ColorTap : MonoBehaviour, IMixedRealityFocusHandler, IMixedRealityPointerHandler
{
    // Allow for editing the type of select action in the Unity Editor.
    [SerializeField]
    private MixedRealityInputAction selectAction = MixedRealityInputAction.None;
    ...

    void IMixedRealityPointerHandler.OnPointerUp(MixedRealityPointerEventData eventData)
    {
        if (eventData.MixedRealityInputAction == selectAction)
        {
            material.color = color_OnHover;
        }
    }

    void IMixedRealityPointerHandler.OnPointerDown(MixedRealityPointerEventData eventData)
    {
        if (eventData.MixedRealityInputAction == selectAction)
        {
            material.color = color_OnSelect;
        }
    }

    void IMixedRealityPointerHandler.OnPointerClicked(MixedRealityPointerEventData eventData) { }
}

BaseEyeFocusHandler específico do olhar

Dado que o olhar pode ser muito diferente de outras entradas de ponteiro, convém ter certeza de reagir somente à entrada de foco se for o olhar e for atualmente o ponteiro de entrada principal. Para essa finalidade, você usaria o que é específico para o BaseEyeFocusHandler acompanhamento ocular e que deriva do BaseFocusHandler. Como mencionado anteriormente, ele só disparará se o direcionamento do olhar for atualmente a entrada de ponteiro primário (ou seja, nenhum raio de mão está ativo). Para obter mais informações, consulte Como dar suporte ao olhar + gestos de mão.

Aqui está um exemplo de EyeTrackingDemo-03-Navigation (Assets/MRTK/Examples/Demos/EyeTracking/Scenes). Nesta demonstração, há dois hologramas 3D que serão ativados dependendo de qual parte do objeto é analisada: se o usuário olhar para o lado esquerdo do holograma, essa parte se moverá lentamente para a frente voltada para o usuário. Se o lado direito for examinado, essa parte se moverá lentamente para a frente. Esse é um comportamento que talvez você não queira ter ativo o tempo todo e também algo que talvez você não queira disparar acidentalmente por um raio de mão ou um olhar de cabeça. Tendo o OnLookAtRotateByEyeGaze anexado, um GameObject girará ao ser examinado.

public class OnLookAtRotateByEyeGaze : BaseEyeFocusHandler
{
    ...

    protected override void OnEyeFocusStay()
    {
        // Update target rotation
        RotateHitTarget();
    }

    ...

    ///
    /// This function computes the rotation of the target to move the currently
    /// looked at aspect slowly to the front.
    ///
    private void RotateHitTarget()
    {
        // Example for querying the hit position of the eye gaze ray using EyeGazeProvider
        Vector3 TargetToHit = (this.gameObject.transform.position - InputSystem.EyeGazeProvider.HitPosition).normalized;

        ...
    }
}

Verifique a documentação da API para obter uma lista completa dos eventos disponíveis:BaseEyeFocusHandler

  • OnEyeFocusStart: Disparado quando o raio do olhar começa a se cruzar com o colisor deste destino.
  • OnEyeFocusStay: Disparado enquanto o raio do olhar está se cruzando com o colisor deste alvo.
  • OnEyeFocusStop: Disparado quando o raio do olhar para de se cruzar com o colisor desse destino.
  • OnEyeFocusDwell: Disparado depois que o raio do olhar se cruza com o colisor desse destino por um período de tempo especificado.

2. EyeTrackingTarget independente específico do olhar

Por fim, fornecemos uma solução que permite tratar a entrada baseada nos olhos completamente independente de outros ponteiros de foco por meio do EyeTrackingTarget script.

Isso tem três vantagens:

  • Você pode garantir que o holograma só esteja reagindo ao olhar do usuário.
  • Isso é independente da entrada primária ativa no momento. Portanto, você pode processar várias entradas ao mesmo tempo - por exemplo, combinando direcionamento rápido de olho com gestos de mão.
  • Vários eventos do Unity já foram configurados para tornar rápido e conveniente manipular e reutilizar comportamentos existentes de dentro do Editor do Unity ou por meio de código.

Há também algumas desvantagens:

  • Mais esforço para lidar com entradas separadas individualmente.
  • Sem degradação elegante: ele só dá suporte ao direcionamento ocular. Se o acompanhamento ocular não estiver funcionando, você precisará de algum fallback adicional.

Semelhante ao BaseFocusHandler, o EyeTrackingTarget vem pronto com vários eventos do Unity específicos do olhar que você pode escutar convenientemente por meio do Editor do Unity (veja o exemplo abaixo) ou usando AddListener() no código:

  • OnLookAtStart()
  • WhileLookingAtTarget()
  • OnLookAway()
  • OnDwell()
  • OnSelected()

No seguinte, explicamos alguns exemplos de como usar o EyeTrackingTarget.

Exemplo nº 1: Notificações inteligentes compatíveis com os olhos

In EyeTrackingDemo-02-TargetSelection (Assets/MRTK/Examples/Demos/EyeTracking/Scenes), você pode encontrar um exemplo para "notificações atentas inteligentes" que reagem ao seu olhar. São caixas de texto 3D que podem ser colocadas na cena e que aumentarão e se voltarão para o usuário ao serem analisadas para facilitar a legibilidade. Enquanto o usuário está lendo a notificação, as informações continuam sendo exibidas de modo nítido e claro. Depois de lê-la e desviar o olhar da notificação, a notificação será automaticamente descartada e desaparecerá. Para obter tudo isso, há alguns scripts de comportamento genéricos que não são específicos do acompanhamento ocular, como:

A vantagem dessa abordagem é que os mesmos scripts podem ser reutilizados por vários eventos. Por exemplo, um holograma pode começar a enfrentar o usuário com base em comandos de voz ou depois de pressionar um botão virtual. Para disparar esses eventos, você pode simplesmente referenciar os métodos que devem ser executados no EyeTrackingTarget script anexado ao GameObject.

Para o exemplo das "notificações atentas inteligentes", ocorre o seguinte:

  • OnLookAtStart(): a notificação começa a...

    • FaceUser.Engage: ... vire em direção ao usuário.
    • ChangeSize.Engage: ... aumento de tamanho (até uma escala máxima especificada).
    • BlendOut.Engage: ... começa a se misturar mais (depois de estar em um estado ocioso mais sutil).
  • OnDwell(): informa ao script BlendOut que a notificação foi analisada suficientemente.

  • OnLookAway(): a notificação começa a...

    • FaceUser.Disengage: ... volte para sua orientação original.
    • ChangeSize.Disengage: ... diminua de volta para seu tamanho original.
    • BlendOut.Disengage: ... começa a se misturar - se OnDwell() foi disparado, misture completamente e destrua, caso contrário, de volta ao seu estado ocioso.

Consideração de design: A chave para uma experiência agradável aqui é ajustar cuidadosamente a velocidade de qualquer um desses comportamentos para evitar causar desconforto reagindo ao olhar do usuário muito rapidamente o tempo todo. Caso contrário, isso pode rapidamente parecer extremamente esmagador.

Notificação de destino

Exemplo nº 2: a gema holográfica gira lentamente ao olhar para ela

Semelhante ao exemplo nº 1, podemos facilmente criar um comentário de foco para nossas pedras preciosas holográficas na EyeTrackingDemo-02-TargetSelection cena (Assets/MRTK/Examples/Demos/EyeTracking/Scenes) que girará lentamente em uma direção constante e em uma velocidade constante (em contraste com o exemplo de rotação acima) ao ser examinado. Tudo o que você precisa é disparar a rotação da joia holográfica do evento WhileLookingAtTarget() do EyeTrackingTarget. Veja mais alguns detalhes:

  1. Crie um script genérico que inclua uma função pública para girar o GameObject ao qual ele está anexado. Abaixo está um exemplo de RotateWithConstSpeedDir.cs em que podemos ajustar a direção de rotação e a velocidade do Editor do Unity.

    using UnityEngine;
    
    namespace Microsoft.MixedReality.Toolkit.Examples.Demos.EyeTracking
    {
        /// <summary>
        /// The associated GameObject will rotate when RotateTarget() is called based on a given direction and speed.
        /// </summary>
        public class RotateWithConstSpeedDir : MonoBehaviour
        {
            [Tooltip("Euler angles by which the object should be rotated by.")]
            [SerializeField]
            private Vector3 RotateByEulerAngles = Vector3.zero;
    
            [Tooltip("Rotation speed factor.")]
            [SerializeField]
            private float speed = 1f;
    
            /// <summary>
            /// Rotate game object based on specified rotation speed and Euler angles.
            /// </summary>
            public void RotateTarget()
            {
                transform.eulerAngles = transform.eulerAngles + RotateByEulerAngles * speed;
            }
        }
    }
    
  2. Adicione o EyeTrackingTarget script ao GameObject de destino e faça referência à função RotateTarget() no gatilho UnityEvent, conforme mostrado na captura de tela abaixo:

    Exemplo de EyeTrackingTarget

Exemplo #3: Pop essas gemas também conhecidas como seleção de destino multi-modal com suporte para olhos

No exemplo anterior, mostramos como é fácil detectar se um destino é examinado e como disparar uma reação a isso. Em seguida, vamos fazer com que as pedras preciosas explodam usando o evento OnSelected() do EyeTrackingTarget. A parte interessante é como a seleção é disparada. O EyeTrackingTarget permite atribuir rapidamente diferentes maneiras de invocar uma seleção:

  • Gesto de pinçamento: a configuração de "Selecionar Ação" como "Selecionar" usa o gesto de mão padrão para disparar a seleção. Isso significa que o usuário pode simplesmente levantar a mão e beliscar o polegar e o dedo indicador juntos para confirmar a seleção.

  • Diga "Selecionar": use o comando de voz padrão "Selecionar" para selecionar um holograma.

  • Diga "Explodir" ou "Pop": para usar comandos de voz personalizados, você precisa seguir duas etapas:

    1. Configurar uma ação personalizada, como "DestroyTarget"

      • Navegar até o MRTK –> Entrada –> Ações de Entrada
      • Clique em "Adicionar uma nova ação"
    2. Configurar os comandos de voz que disparam essa ação, como "Explodir" ou "Pop"

      • Navegar até o MRTK –> Entrada –> Fala
      • Clique em "Adicionar um novo comando de fala"
        • Associar a ação que você acabou de criar
        • Atribuir um KeyCode para permitir disparar a ação por meio de um botão pressionar

Exemplo de EyeTrackingTarget de comandos de voz

Quando uma joia é selecionada, ela explode, fazendo um som e desaparece. Isso é tratado pelo HitBehaviorDestroyOnSelect script. Você tem duas opções:

  • No Editor do Unity: Você pode simplesmente vincular o script anexado a cada um de nossos modelos de gem para o evento OnSelected() Unity no Editor do Unity.
  • No código: Se você não quiser arrastar e soltar GameObjects, você também pode simplesmente adicionar um ouvinte de eventos diretamente ao seu script.
    Aqui está um exemplo de como fizemos isso no HitBehaviorDestroyOnSelect script:
/// <summary>
/// Destroys the game object when selected and optionally plays a sound or animation when destroyed.
/// </summary>
[RequireComponent(typeof(EyeTrackingTarget))] // This helps to ensure that the EyeTrackingTarget is attached
public class HitBehaviorDestroyOnSelect : MonoBehaviour
{
    ...
    private EyeTrackingTarget myEyeTrackingTarget = null;

    private void Start()
    {
        myEyeTrackingTarget = this.GetComponent<EyeTrackingTarget>();

        if (myEyeTrackingTarget != null)
        {
            myEyeTrackingTarget.OnSelected.AddListener(TargetSelected);
        }
    }

    ...

    ///
    /// This is called once the EyeTrackingTarget detected a selection.
    ///
    public void TargetSelected()
    {
        // Play some animation
        // Play some audio effect
        // Handle destroying the target appropriately
    }
}

Exemplo nº 4: usar os raios das mãos e a entrada do olhar juntos

Os raios manuais têm prioridade sobre o direcionamento da cabeça e do olhar. Isso significa que, se os raios manuais estiverem habilitados, no momento em que as mãos entrarem em exibição, o raio de mão agirá como o ponteiro primário. No entanto, pode haver situações em que você deseja usar raios manuais enquanto ainda detecta se um usuário está olhando para um determinado holograma. Muito fácil. Essencialmente, você precisa de duas etapas:

1. Habilitar o raio manual: para habilitar o raio manual, vá para Realidade Misturada Kit de Ferramentas –> Entrada –> Ponteiros. No EyeTrackingDemo-00-RootScene em que Realidade Misturada Toolkit é configurado uma vez para todas as cenas de demonstração de acompanhamento ocular, você deve ver o EyeTrackingDemoPointerProfile. Você pode criar um novo Perfil de Entrada do zero ou adaptar o acompanhamento ocular atual:

  • Do zero: Na guia Ponteiros , selecione o DefaultMixedRealityInputPointerProfile no menu de contexto. Esse é o perfil de ponteiro padrão que já tem o raio manual habilitado! Para alterar o cursor padrão (um ponto branco opaco), basta clonar o perfil e criar seu próprio perfil de ponteiro personalizado. Em seguida, substitua DefaultCursor por EyeGazeCursor em Prefab do Cursor de Foco.
  • Com base no EyeTrackingDemoPointerProfile existente: clique duas vezes no EyeTrackingDemoPointerProfile e adicione a seguinte entrada em Opções de Ponteiro:
    • Tipo de controlador: 'Mão Articulada', 'Windows Mixed Reality'
    • Handedness: Qualquer
    • Pré-fabricado de ponteiro: DefaultControllerPointer

2. Detecte que um holograma é examinado: use o EyeTrackingTarget script para habilitar a detecção de que um holograma é examinado conforme descrito acima. Você também pode dar uma olhada no FollowEyeGaze script de exemplo para se inspirar, pois isso mostra um holograma seguindo o olhar (por exemplo, um cursor) se os raios manuais estão habilitados ou não.

Agora, quando você começa as cenas de demonstração de rastreamento ocular, você deve ver um raio vindo de suas mãos. Por exemplo, na demonstração de seleção de destino de acompanhamento ocular, o círculo semitransparente ainda está seguindo seu olhar e as pedras preciosas respondem se elas são vistas ou não, enquanto os botões de menu de cena superior usam o ponteiro de entrada primário (suas mãos).


De volta ao "Rastreamento de olhos no MixedRealityToolkit"