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 de foco ocular 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 de mão e comandos de voz:

  • Look & Say "Select" (comando de voz padrão)
  • Procure & Diga "Explodir" ou "Pop" (comandos de voz personalizados)
  • Botão Olhar & Bluetooth
  • Olhe & Pinch (ou seja, segure a mão na sua frente e reúna o polegar e o dedo indicador)

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 é 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:

  • Vá até o botão e cutuque-o
  • Olhe para ele à distância e diga "selecionar"
  • Direcionar o botão usando um raio de mão e executar uma pinçagem 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 priorizado no momento disparar um evento. Observe que, se os raios de mão estiverem habilitados, o ponteiro de foco do foco da cabeça ou do olhar será desabilitado assim que as mãos entrarem em exibição.

Importante

Observe que, se os raios de mão estiverem habilitados, o ponteiro de foco do 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 "olhar e pinçar", será necessário desabilitar o raio de mão. Em nossas cenas de exemplo de acompanhamento ocular, desabilitamos o raio da mão para permitir a apresentação de interações mais avançadas usando olhos + movimentos de mão - consulte, por exemplo, Posicionamento com suporte ocular.

2. Use o foco dos olhos e os raios de mão 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 configuraçã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 marcar. Se o usuário não tiver as mãos ocupadas, seria instintivo simplesmente tocar na caixa marcar 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 lugar, você deseja permitir que o usuário role diretamente pelas instruções usando o olhar e simplesmente olhe para uma caixa de marcar e diga "marcar!".

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

1. Usar manipuladores genéricos de foco e ponteiro

Se o acompanhamento ocular estiver configurado corretamente (consulte 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, foco na cabeça ou raio de mão). Isso oferece a grande vantagem de uma maneira flexível de interagir com seus hologramas definindo o tipo de foco main em seu Perfil de Ponteiro de Entrada do MRTK, dependendo das necessidades do usuário, deixando o código inalterado. Isso permite alternar entre o olhar ou a cabeça sem alterar uma linha de código ou substituir raios de mão por direcionamento ocular para interações distantes.

Concentrando-se 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 fará com que eles reajam à 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 pinçando ou dizendo "selecionar". A ação necessária para disparar o evento é definida pelo eventData.MixedRealityInputAction == selectAction qual podemos definir o tipo de selectAction no Editor do Unity – por padrão, é a ação "Selecionar". Os tipos de MixedRealityInputActions disponíveis podem ser configurados no Perfil do MRTK por meio de Perfil de Configuração do MRTK ->Entrada -Ações de>Entrada.

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

Considerando que o foco ocular pode ser muito diferente de outras entradas de ponteiro, convém garantir que você reaja apenas à entrada de foco se for o foco e for o ponteiro de entrada principal no momento. Para essa finalidade, você usaria o BaseEyeFocusHandler que é específico para o acompanhamento ocular e que deriva do BaseFocusHandler. Conforme mencionado anteriormente, ele só será disparado se o direcionamento do olhar for atualmente a entrada do ponteiro primário (ou seja, nenhum raio de mão está ativo). Para obter mais informações, consulte Como dar suporte a olhares + 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 foco na cabeça. Tendo o OnLookAtRotateByEyeGaze anexado, um GameObject girará enquanto estiver sendo 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 do BaseEyeFocusHandler:

  • OnEyeFocusStart: Disparado quando o raio do olhar começa a se cruzar com o colisor deste alvo.
  • 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 deste alvo.
  • OnEyeFocusDwell: Disparado depois que o raio do olhar 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 em 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 de olho rápido 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.

Também há 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()

A seguir, explicamos alguns exemplos de como usar o EyeTrackingTarget.

Exemplo nº 1: notificações inteligentes com suporte ocular

No EyeTrackingDemo-02-TargetSelection (Assets/MRTK/Examples/Demos/EyeTracking/Scenes), você pode encontrar um exemplo de "notificações atentas inteligentes" que reagem ao seu olhar. Essas são caixas de texto 3D que podem ser colocadas na cena e que serão ampliadas e giradas em direção ao usuário ao serem examinadas para facilitar a legibilidade. Enquanto o usuário está lendo a notificação, as informações continuam sendo exibidas nítidas e claras. Depois de lê-la e desviar o olhar da notificação, a notificação será automaticamente descartada e desaparecerá. Para conseguir 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 ser voltado para 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 de "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: ... aumentar 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 do BlendOut que a notificação foi analisada o suficiente.

  • 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 joia holográfica gira lentamente ao olhar para ela

Semelhante ao Exemplo nº 1, podemos criar facilmente um feedback de foco para nossa cena de gemas 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 do gem holográfico 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. Veja abaixo um exemplo de RotateWithConstSpeedDir.cs em que podemos ajustar a direção e a velocidade de rotação 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 nº 3: pop dessas gemas, também conhecidas como seleção de destino com suporte multimoda com foco nos 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 gemas 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çagem: 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 pinçar 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"

      • Navegue até 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"

      • Navegue até 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 o disparo da ação por meio de um pressionamento de botão

Exemplo de comandos de voz EyeTrackingTarget

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 gem para o evento OnSelected() Unity no Editor do Unity.
  • No código: Se você não quiser arrastar e soltar GameObjects, também poderá simplesmente adicionar um ouvinte de eventos diretamente ao 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 raios de mão e entrada de foco com os olhos juntos

Os raios de mão têm prioridade sobre o direcionamento da cabeça e do olhar. Isso significa que, se os raios de mão estiverem habilitados, no momento em que as mãos aparecerem, o raio de mão atuará 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 de mão: para habilitar o raio de mão, vá para Realidade Misturada Toolkit –> 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ê deverá 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 DefaultMixedRealityInputPointerProfile no menu de contexto. Este é o perfil de ponteiro padrão que já tem o raio de mão 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 em 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 rastreamento ocular, o círculo semitransparente ainda está seguindo seu olhar e as joias respondem se 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 "Acompanhamento ocular no MixedRealityToolkit"