Seleção de destino suportada por olhos — MRTK2

MRTK

Esta página aborda diferentes opções para aceder a dados de olhar para os olhos e eventos específicos de olhar para os olhos para selecionar destinos no MRTK. O controlo ocular permite seleções de destino rápidas e sem esforço através de uma combinação de informações sobre o que um utilizador está a ver com entradas adicionais, como controlo manual e comandos de voz:

  • Procurar & Diga "Selecionar" (comando de voz predefinido)
  • Procure & Diga "Explode" ou "Pop" (comandos de voz personalizados)
  • Procurar & botão Bluetooth
  • Olhe & Dedos (ou seja, levante a mão à sua frente e junte o polegar e o dedo indicador)

Para selecionar conteúdo holográfico com o olhar atento, existem várias opções:

1. Utilize o ponteiro de foco principal:

Isto pode ser entendido como o seu cursor priorizado. Por predefinição, se as mãos estiverem à vista, isto seria raios de mão. Se não existirem mãos à vista, o ponteiro priorizado será olhar para a cabeça ou para os olhos. Assim, tenha em atenção que, com base no olhar atual da cabeça ou dos olhos, é suprimido como uma entrada de cursor se forem utilizados raios da mão.

Por exemplo:

Um utilizador quer selecionar um botão holográfico distante. Enquanto programador, quer fornecer uma solução flexível que permita ao utilizador realizar estas tarefas em várias condições:

  • Ir até ao botão e picar
  • Observe-o à distância e diga "selecionar"
  • Direcionar o botão através de um raio-mão e fazer um gesto de aproximar os dedos Neste caso, a solução mais flexível é utilizar o processador de foco principal, uma vez que irá notificá-lo sempre que o ponteiro de foco principal atualmente priorizado acionar um evento. Tenha em atenção que, se os raios das mãos estiverem ativados, o ponteiro de foco da cabeça ou do olho será desativado assim que as mãos estiverem visíveis.

Importante

Tenha em atenção que, se os raios das mãos estiverem ativados, o ponteiro de foco da cabeça ou do olho será desativado assim que as mãos estiverem visíveis. Se quiser suportar uma interação "olhar e beliscar", tem de desativar o raio da mão. Nas nossas cenas de exemplo de controlo de olhos, desativamos o raio da mão para permitir a apresentação de interações mais ricas com olhos + movimentos de mão - veja, por exemplo, Posicionamento Suportado pelos Olhos.

2. Utilize o foco ocular e os raios das mãos ao mesmo tempo:

Podem existir instâncias em que pretende ser mais específico que tipo de ponteiros de foco podem acionar determinados eventos e permitir a utilização simultânea de múltiplas técnicas de interação.

Por exemplo: na sua aplicação, um utilizador pode utilizar raios de mão distantes para manipular alguma configuração mecânica holográfica, por exemplo, agarrar sem soltar algumas partes distantes do motor holográfico e mantê-las no lugar. Ao fazê-lo, o utilizador tem de seguir várias instruções e gravar o seu progresso ao marcar algumas caixas de verificação. Se o utilizador não tiver as mãos ocupadas, seria instintivo tocar na caixa de verificação ou selecioná-la utilizando um raio de mão. No entanto, se o utilizador tiver as mãos ocupadas, como no nosso caso com algumas peças do motor holográfico no lugar, quer permitir que o utilizador percorra facilmente as instruções com o olhar e simplesmente olhe para uma caixa de verificação e diga "verifique!".

Para ativar esta opção, tem de utilizar um script EyeTrackingTarget específico que seja independente do MRTK FocusHandlers principal e que será abordado mais abaixo.

1. Utilize processadores genéricos de foco e ponteiro

Se a monitorização ocular estiver configurada corretamente (consulte Configuração básica do MRTK para utilizar a monitorização ocular), permitir que os utilizadores selecionem hologramas utilizando os olhos é igual a qualquer outra entrada de foco (por exemplo, olhar para a cabeça ou raio da mão). Isto proporciona a grande vantagem de uma forma flexível de interagir com os hologramas ao definir o tipo de foco principal no Perfil de Ponteiro de Entrada do MRTK, consoante as necessidades do utilizador, mantendo o código inalterado. Isto permite alternar entre o olhar da cabeça ou dos olhos sem alterar uma linha de código ou substituir os raios da mão por filtragem ocular para interações distantes.

Focar-se num holograma

Para detetar quando um holograma está focado, utilize a interface "IMixedRealityFocusHandler" que lhe fornece dois membros da interface: OnFocusEnter e OnFocusExit.

Eis um exemplo simples de ColorTap.cs para alterar a cor de um holograma ao ser analisado.

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

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

Selecionar um holograma focado

Para selecionar um holograma focado, utilize PointerHandler para escutar eventos de entrada para confirmar uma seleção. Por exemplo, adicionar o IMixedRealityPointerHandler fará com que reajam a entradas de ponteiro simples. A interface IMixedRealityPointerHandler requer a implementação dos três membros da interface seguintes: OnPointerUp, OnPointerDown e OnPointerClicked.

No exemplo abaixo, alteramos a cor de um holograma ao olhar para o mesmo e aproximar ou dizer "selecionar". A ação necessária para acionar o evento é definida pelo eventData.MixedRealityInputAction == selectAction qual podemos definir o tipo de no Editor do selectAction Unity – por predefinição, é a ação "Selecionar". Os tipos de MixedRealityInputActions disponíveis podem ser configurados no Perfil MRTK através 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, pode querer certificar-se de que só reage à entrada de foco se for o olhar e for atualmente o ponteiro de entrada principal. Para esta finalidade, utilizaria o BaseEyeFocusHandler que é específico do controlo ocular e que deriva do BaseFocusHandler. Como mencionado anteriormente, só será acionado se a segmentação de olhar para os olhos for atualmente a entrada principal do ponteiro (ou seja, nenhum raio de mão está ativo). Para obter mais informações, consulte Como suportar o olhar atento + gestos de mão.

Eis um exemplo de EyeTrackingDemo-03-Navigation (Assets/MRTK/Examples/Demos/EyeTracking/Scenes). Nesta demonstração, existem dois hologramas 3D que serão ativados consoante a parte do objeto que é vista: se o utilizador olhar para o lado esquerdo do holograma, essa parte irá mover-se lentamente para a frente do utilizador. Se o lado direito for analisado, essa parte irá mover-se lentamente para a frente. Este é um comportamento que pode não querer ter sempre ativo e também algo que pode não querer acionar acidentalmente por um raio da mão ou olhar para a cabeça. Ao anexar, OnLookAtRotateByEyeGaze um GameObject irá rodar enquanto é analisado.

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;

        ...
    }
}

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

  • OnEyeFocusStart: Acionado assim que o raio de olhar para os olhos começa a intersectar com o colisor deste alvo.
  • OnEyeFocusStay: Acionado enquanto o raio de olhar olhado se cruza com o colisor deste alvo.
  • OnEyeFocusstop: Acionado assim que o raio de olhar para os olhos deixa de se cruzar com o colisor deste alvo.
  • OnEyeFocusDwell: Acionado assim que o raio de olhar para os olhos se cruze com o colisor deste alvo durante um determinado período de tempo.

2. EyeTrackingTarget independente específico do olhar

Por fim, fornecemos-lhe uma solução que lhe permite tratar entradas baseadas nos olhos completamente independentes de outros ponteiros de foco através do EyeTrackingTarget script.

Isto tem três vantagens:

  • Pode certificar-se de que o holograma só está a reagir ao olhar do utilizador.
  • Isto é independente da entrada primária atualmente ativa. Por conseguinte, pode processar múltiplas entradas de uma só vez, por exemplo, ao combinar a segmentação rápida dos olhos com gestos de mão.
  • Já foram configurados vários eventos do Unity para tornar mais rápido e conveniente lidar e reutilizar comportamentos existentes a partir do Editor do Unity ou através de código.

Também existem algumas desvantagens:

  • Mais esforço para processar entradas separadas individualmente.
  • Sem degradação elegante: suporta apenas a segmentação ocular. Se o controlo ocular não estiver a funcionar, precisará de uma contingência adicional.

À semelhança do BaseFocusHandler, o EyeTrackingTarget vem pronto com vários eventos do Unity específicos do olhar que pode escutar convenientemente através do Editor do Unity (veja o exemplo abaixo) ou ao utilizar AddListener() no código:

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

No seguinte, vamos guiá-lo através de alguns exemplos sobre como utilizar o EyeTrackingTarget.

Exemplo n.º 1: Notificações inteligentes suportadas por olhos

No EyeTrackingDemo-02-TargetSelection (Assets/MRTK/Examples/Demos/EyeTracking/Scenes), pode encontrar um exemplo de "notificações inteligentes e atentas" que reagem ao olhar atento. Estas são caixas de texto 3D que podem ser colocadas no cenário e que irão aumentar e virar-se suavemente para o utilizador quando for analisado para facilitar a legibilidade. Enquanto o utilizador lê a notificação, as informações continuam a ser apresentadas de forma nítida e clara. Depois de lê-la e afastar-se da notificação, a notificação será automaticamente dispensada e desaparece gradualmente. Para alcançar tudo isto, existem alguns scripts de comportamento genéricos que não são específicos do controlo ocular, tais como:

A vantagem desta abordagem é que os mesmos scripts podem ser reutilizados por vários eventos. Por exemplo, um holograma pode começar a encarar o utilizador com base em comandos de voz ou depois de premir um botão virtual. Para acionar estes eventos, pode simplesmente referenciar os métodos que devem ser executados no EyeTrackingTarget script anexado ao seu GameObject.

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

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

    • FaceUser.Engage: ... vire-se para o utilizador.
    • ChangeSize.Engage: ... aumentar o tamanho (até uma escala máxima especificada).
    • BlendOut.Engage: ... começa a misturar-se em mais (depois de estar num estado inativo mais subtil).
  • OnDwell(): informa o script BlendOut de que a notificação foi suficientemente consultada.

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

    • FaceUser.Disengage: ... voltar à sua orientação original.
    • ChangeSize.Disengage: ... diminuir novamente para o tamanho original.
    • BlendOut.Disengage: ... começa a misturar-se - Se OnDwell() tiver sido acionado, misture completamente e destrua, caso contrário volte ao seu estado inativo.

Consideração de design: A chave para uma experiência agradável aqui é otimizar cuidadosamente a velocidade de qualquer um destes comportamentos para evitar causar desconforto reagindo ao olhar do utilizador demasiado rapidamente. Caso contrário, isto pode rapidamente parecer extremamente avassalador.

Notificação de Destino

Exemplo n.º 2: a gem holográfica roda lentamente ao olhar para a mesma

À semelhança do Exemplo n.º 1, podemos criar facilmente um feedback sensível ao rato para os nossos gems holográficos na EyeTrackingDemo-02-TargetSelection cena (Assets/MRTK/Examples/Demos/EyeTracking/Scenes) que irá rodar lentamente numa direção constante e a uma velocidade constante (em contraste com o exemplo de rotação acima) ao ser analisado. Tudo o que precisa é de acionar a rotação da gem holográfica do evento WhileLookingAtTarget() do EyeTrackingTarget. Eis mais alguns detalhes:

  1. Crie um script genérico que inclua uma função pública para rodar o GameObject ao qual está anexado. Segue-se um exemplo de RotateWithConstSpeedDir.cs , onde podemos ajustar a direção da 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 referencie a função RotateTarget() no acionador UnityEvent, conforme mostrado na captura de ecrã abaixo:

    Exemplo de EyeTrackingTarget

Exemplo n.º 3: Pop those gems aka multi-modal eye-gaze-supported target selection

No exemplo anterior, mostrámos como é fácil detetar se um destino é analisado e como desencadear uma reação a isso. Em seguida, vamos fazer com que as jóias expludam com o evento OnSelected() do EyeTrackingTarget. A parte interessante é a forma como a seleção é acionada. O EyeTrackingTarget permite atribuir rapidamente diferentes formas de invocar uma seleção:

  • Gesto de aproximar os dedos: definir "Selecionar Ação" como "Selecionar" utiliza o gesto de mão predefinido para acionar a seleção. Isto significa que o utilizador pode simplesmente levantar a mão e aproximar o polegar e o dedo indicador para confirmar a seleção.

  • Diga "Selecionar": utilize o comando de voz predefinido "Selecionar" para selecionar um holograma.

  • Diga "Explode" ou "Pop": para utilizar comandos de voz personalizados, tem de seguir dois passos:

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

      • Navegar para MRTK –> Entrada –> Ações de Entrada
      • Clique em "Adicionar uma nova ação"
    2. Configurar os comandos de voz que acionam esta ação, como "Explode" ou "Pop"

      • Navegue para MRTK –> Entrada –> Voz
      • Clique em "Adicionar um novo comando de voz"
        • Associar a ação que acabou de criar
        • Atribuir um KeyCode para permitir o acionamento da ação através de um botão premido

Comandos de voz Exemplo eyeTrackingTarget

Quando uma jóia é selecionada, explode, faz um som e desaparece. Isto é processado pelo HitBehaviorDestroyOnSelect script. Tem duas opções:

  • No Editor do Unity: Pode simplesmente ligar o script anexado a cada um dos nossos modelos gem ao evento Do Unity OnSelected() no Editor do Unity.
  • No código: Se não quiser arrastar e largar GameObjects, também pode simplesmente adicionar um serviço de escuta de eventos diretamente ao script.
    Eis um exemplo de como o fizemos 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: Utilizar raios manos e entradas de olhar para os olhos em conjunto

Os raios das mãos têm prioridade sobre o alvo da cabeça e do olhar. Isto significa que, se os raios da mão estiverem ativados, no momento em que as mãos entrarem em vista, o raio da mão funcionará como o ponteiro principal. No entanto, podem existir situações em que pretende utilizar raios-mão enquanto deteta se um utilizador está a olhar para um determinado holograma. É fácil! Essencialmente, precisa de dois passos:

1. Ative o raio da mão: para ativar o raio da mão, aceda a Mixed Reality Toolkit -> Entrada -> Ponteiros. No EyeTrackingDemo-00-RootScene, onde Mixed Reality Toolkit está configurado uma vez para todas as cenas de demonstração de controlo ocular, deverá ver EyeTrackingDemoPointerProfile. Pode criar um novo Perfil de Entrada do zero ou adaptar o controlo ocular atual:

  • Do zero: No separador Ponteiros , selecione DefaultMixedRealityInputPointerProfile no menu de contexto. Este é o perfil de ponteiro predefinido que já tem o raio manual ativado! Para alterar o cursor predefinido (um ponto branco opaco), basta clonar o perfil e criar o seu próprio perfil de ponteiro personalizado. Em seguida, substitua DefaultCursor por EyeGazeCursor em Gaze Cursor Prefab.
  • Com base no EyeTrackingDemoPointerProfile existente: faça duplo clique no EyeTrackingDemoPointerProfile e adicione a seguinte entrada em Opções de Ponteiro:
    • Tipo de Controlador: 'Mão Articulada', 'Windows Mixed Reality'
    • Mão de mão: Qualquer
    • Prefab do Ponteiro: DefaultControllerPointer

2. Detete que um holograma é analisado: utilize o EyeTrackingTarget script para ativar a deteção de que um holograma é analisado conforme descrito acima. Também pode dar uma vista de olhos ao FollowEyeGaze script de exemplo para se inspirar, uma vez que este está a mostrar um holograma a seguir ao olhar (por exemplo, um cursor) quer os raios das mãos estejam ativados ou não.

Agora, quando começares as cenas de demonstração de controlo ocular, devias ver um raio a vir das tuas mãos. Por exemplo, na demonstração de seleção de destino de controlo ocular, o círculo semi-transparente continua a seguir o olhar e as jóias respondem quer sejam ou não olhadas, enquanto os botões de menu da cena superior utilizam o ponteiro de entrada principal (as mãos) em vez disso.


Voltar ao "Eye tracking in the MixedRealityToolkit"