Ponteiros — MRTK2
Este artigo explica como configurar e responder à entrada ponteiro na prática. Para entender melhor como controlar vários ponteiros em um alto nível, consulte a Arquitetura do Ponteiro.
Os ponteiros são instânciados automaticamente em runtime quando um novo controlador é detectado. Mais de um ponteiro pode ser anexado a um controlador. Por exemplo, com o perfil de ponteiro padrão, os controladores Windows Mixed Reality obtêm uma linha e um ponteiro parabólico para seleção e teletransporte normais, respectivamente.
Configuração do ponteiro
Os ponteiros são configurados como parte do sistema de entrada no MRTK por meio de um MixedRealityPointerProfile
. Esse tipo de perfil é atribuído a um MixedRealityInputSystemProfile
inspetor de configuração do MRTK. O perfil Ponteiro determina o cursor, os tipos de Ponteiros disponíveis no runtime e como esses ponteiros se comunicam entre si para decidir qual deles está ativo.
Extensão de apontamento – define a distância máxima para a qual um ponteiro pode interagir com um GameObject.
Apontando máscaras de camada do Raycast – esta é uma matriz priorizada de LayerMasks para determinar com quais possíveis GameObjects qualquer ponteiro determinado pode interagir e a ordem de interação a ser tentada. Isso pode ser útil para garantir que os Ponteiros interajam primeiro com elementos da interface do usuário antes de outros objetos de cena.
Configuração de opções de ponteiro
A configuração padrão do Perfil do Ponteiro MRTK inclui as seguintes classes de ponteiro e pré-fabricados associados prontos para uso. A lista de ponteiros disponíveis para o sistema em runtime é definida em Opções de Ponteiro no perfil Ponteiro. Os desenvolvedores podem utilizar essa lista para reconfigurar ponteiros existentes, adicionar novos ponteiros ou excluir um.
Cada entrada ponteiro é definida pelo seguinte conjunto de dados:
Tipo de controlador – o conjunto de controladores para os quais um ponteiro é válido.
- Por exemplo, o PokePointer é responsável por "cutucar" objetos com um dedo e, por padrão, é marcado como suporte apenas ao tipo de controlador de mão articulado. Os ponteiros só são instanciados quando um controlador fica disponível e, em particular, o Tipo de Controlador define com quais controladores esse pré-fabricado de ponteiro pode ser criado.
Handedness - permite que um ponteiro seja instanciado apenas para uma mão específica (esquerda/direita)
Observação
Definir a propriedade Handedness de uma entrada pointer como None efetivamente a desabilitará do sistema como uma alternativa para remover esse Ponteiro da lista.
- Pré-fabricado de ponteiro – esse ativo de pré-fabricado será instanciado quando um controlador que corresponde ao tipo de controlador especificado e à entrega começar a ser rastreado.
É possível ter vários ponteiros associados a um controlador. Por exemplo, em DefaultHoloLens2InputSystemProfile
(Assets/MRTK/SDK/Profiles/HoloLens2/) o controlador de mão articulado está associado ao PokePointer, Ao GrabPointer e ao DefaultControllerPointer (ou seja, raios manuais).
Observação
O MRTK fornece um conjunto de pré-fabricados de ponteiro em Ativos/MRTK/SDK/Recursos/UX/Pré-fabricados/Ponteiros. Um novo pré-fabricado personalizado pode ser criado desde que contenha um dos scripts de ponteiro em Assets/MRTK/SDK/Features/UX/Scripts/Pointers ou qualquer outro script que implemente IMixedRealityPointer
.
Configuração do cursor
O cursor Gaze é configurável diretamente por meio da GazeCursorPrefab
propriedade no MixedRealityInputSystemProfile
Editor. Para configurar o cursor usado para outros ponteiros, você precisa alterar o CursorPrefab
pré-fabricado usado no campo do correspondente BaseControllerPointer
. Para alterar o cursor programaticamente, modifique a BaseCursor
propriedade no comportamento correspondente IMixedRealityPointer
.
Consulte nossos pré-fabricados de cursor em Ativos/MRTK/SDK/Recursos/UX/Prefabs/Cursores para obter exemplos de implementações do comportamento do cursor. Em particular, o DefaultGazeCursor fornece uma implementação robusta de alteração do gráfico do cursor com base no estado contextual.
Classes de ponteiro padrão
As classes a seguir são os ponteiros mrtk prontos para uso disponíveis e definidos no perfil de ponteiro mrtk padrão descrito acima. Cada pré-fabricado de ponteiro fornecido em Assets/MRTK/SDK/Features/UX/Prefabs/Pointers contém um dos componentes de ponteiro anexados.
Ponteiros distantes
LinePointer
LinePointer, uma classe de ponteiro base, desenha uma linha da origem da entrada (ou seja, o controlador) na direção do ponteiro e dá suporte a uma conversão de raio único nessa direção. Geralmente, as classes filhos, como os ShellHandRayPointer
ponteiros de teletransporte, são instanciadas e utilizadas (que também desenham linhas para indicar onde o teletransporte acabará) em vez dessa classe, que fornece principalmente funcionalidades comuns.
Para controladores de movimento como em Oculus, Vive e Windows Mixed Reality, a rotação corresponderá à rotação do controlador. Para outros controladores, como HoloLens 2 mãos articuladas, a rotação corresponde à pose de apontamento fornecida pelo sistema da mão.

CurvePointer
O CurvePointer estende a classe LinePointer permitindo conversões de raios de várias etapas ao longo de uma curva. Essa classe de ponteiro base é útil para instâncias curvas, como ponteiros de teletransporte, em que a linha se curva consistentemente em uma parábola.
ShellHandRayPointer
A implementação do ShellHandRayPointer, que se estende de , é usada como o padrão para o Perfil de LinePointer
Ponteiro mrtk. O prefab DefaultControllerPointer implementa a ShellHandRayPointer
classe.
GGVPointer
Também conhecido como ponteiro GGV (Olhar/Gesto/Voz), o GGVPointer alimenta HoloLens interações de toque e aparência de 1 estilo, principalmente por meio da interação Gaze e Air Tap ou Gaze e seleção de voz. A posição e a direção do ponteiro GGV são controladas pela posição e rotação da cabeça.
TouchPointer
O TouchPointer é responsável por trabalhar com entrada do Unity Touch (ou seja, tela sensível ao toque). Essas são "interações distantes" porque o ato de tocar na tela vai converter um raio da câmera para um local potencialmente distante na cena.
MousePointer
O MousePointer alimenta uma tela para o world raycast para interações distantes, mas para o mouse em vez de toque.
Observação
O suporte ao mouse não está disponível por padrão no MRTK, mas pode ser habilitado adicionando um novo Provedor de Dados de entrada do tipo MouseDeviceManager
ao perfil de entrada mrtk e atribuindo o MixedRealityMouseInputProfile
ao provedor de dados.
Ponteiros próximos
PokePointer
O PokePointer é usado para interagir com objetos de jogo que dão suporte a "interação quase tocável". que são GameObjects que têm um script anexado NearInteractionTouchable
. No caso do UnityUI, esse ponteiro procura NearInteractionTouchableUnityUIs. O PokePointer usa um SphereCast para determinar o elemento sensível ao toque mais próximo e é usado para alimentar coisas como os botões pressíveis.
Ao configurar o GameObject com o NearInteractionTouchable
componente, configure o parâmetro localForward para apontar para fora da frente do botão ou outro objeto que deve ser tocável. Verifique também se os limites do touchable correspondem aos limites do objeto tocáveis.
Propriedades úteis do Ponteiro poke:
- TouchableDistance: distância máxima com a qual uma superfície sensível ao toque pode ser interagida
- Visuais: objeto game usado para renderizar o visual da ponta do dedo (o anel no dedo, por padrão).
- Linha: linha opcional a ser desenhada da ponta do dedo para a superfície de entrada ativa.
- Máscaras de Camada de Poke – uma matriz priorizada de LayerMasks para determinar com quais possíveis GameObjects o ponteiro pode interagir e a ordem de interação a ser tentada. Observe que um GameObject também deve ter um
NearInteractionTouchable
componente para interagir com um ponteiro de cutucada.

SpherePointer
O SpherePointer usa UnityEngine.Physics.OverlapSphere para identificar o objeto mais NearInteractionGrabbable
próximo para interação, o que é útil para entradas "agarráveis", como a ManipulationHandler
. Semelhante ao PokePointer
/NearInteractionTouchable
par funcional, para ser interacionável com o Ponteiro do Sphere, o objeto de jogo deve conter um componente que seja o NearInteractionGrabbable
script.

Propriedades úteis do Ponteiro do Sphere:
- Sphere Cast Radius: o raio da esfera usada para consultar objetos que podem ser capturados.
- Margem de objeto próximo: a distância na parte superior do Raio de Conversão do Sphere para consultar se um objeto está próximo ao ponteiro. Raio total de detecção de objeto próximo é Sphere Cast Radius + Near Object Margin
- Ângulo próximo do setor de objetos: o ângulo ao redor do eixo dianteiro do ponteiro para consultar objetos próximos. Faz a
IsNearObject
função de consulta como um cone. Isso é definido como 66 graus por padrão para corresponder ao comportamento do Hololens 2
- Fator de suavização de objeto próximo: fator de suavização para detecção de objeto próximo. Se um objeto for detectado no Raio do Objeto Próximo, o raio consultado se tornará o Raio do Objeto Próximo * (1 + Fator de Suavização de Objeto Próximo) para reduzir a sensibilidade e dificultar a saída do intervalo de detecção de um objeto.
- Capturar Máscaras de Camada – uma matriz priorizada de LayerMasks para determinar com quais possíveis GameObjects o ponteiro pode interagir e a ordem de interação a ser tentada. Observe que um GameObject também deve ter um
NearInteractionGrabbable
para interagir com um SpherePointer.Observação
A camada de Reconhecimento Espacial está desabilitada no pré-fabricado padrão do GrabPointer fornecido pelo MRTK. Isso é feito para reduzir o impacto no desempenho de fazer uma consulta de sobreposição de esfera com a malha espacial. Você pode habilitar isso modificando o prefab do GrabPointer.
- Ignorar Colisores Não em FOV - Se deve ignorar colisores que podem estar perto do ponteiro, mas não realmente no FOV visual. Isso pode evitar capturas acidentais e permitirá que os raios manuais ativem quando você pode estar perto de um agarrável, mas não pode vê-lo. O Visual FOV é definido por meio de um cone em vez do frusto típico por motivos de desempenho. Esse cone é centralizado e orientado da mesma forma que o frusto da câmera com um raio igual a meia altura de exibição (ou FOV vertical).

Ponteiros de teletransporte
TeleportPointer
gerará uma solicitação de teletransporte quando a ação for tomada (ou seja, o botão de teletransporte é pressionado) para mover o usuário.ParabolicTeleportPointer
gerará uma solicitação de teletransporte quando a ação for tomada (ou seja, o botão de teletransporte é pressionado) com um raycast de linha parabólica para mover o usuário.

Suporte de ponteiro para plataformas de realidade misturada
A tabela a seguir detalha os tipos de ponteiro que normalmente são usados para as plataformas comuns no MRTK. OBSERVAÇÃO: é possível adicionar diferentes tipos de ponteiro a essas plataformas. Por exemplo, você pode adicionar um ponteiro Poke ou ponteiro Sphere para VR. Além disso, dispositivos VR com um gamepad poderiam usar o ponteiro GGV.
Ponteiro | 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 |
Interações de ponteiro por meio de código
Interfaces de evento pointer
MonoBehaviours que implementam uma ou mais das interfaces a seguir e são atribuídos a um GameObject com um Collider
ponteiro receberão eventos de interações do Ponteiro conforme definido pela interface associada.
Evento | Descrição | Manipulador |
---|---|---|
Antes da alteração do foco/foco alterado | Gerado em ambos os objetos do jogo perdendo o foco e aquele ganhando-o sempre que um ponteiro muda de foco. | IMixedRealityFocusChangedHandler |
Focus Enter/Exit | Gerado no objeto do jogo ganhando foco quando o primeiro ponteiro entra nele e no que perde o foco quando o último ponteiro o deixa. | IMixedRealityFocusHandler |
Ponteiro para baixo / Arrastado / Para cima / Clicado | Gerado para o relatório, pressione, arraste e solte. | IMixedRealityPointerHandler |
Touch Started/Updated/Completed | Gerados por ponteiros com reconhecimento de toque gostam PokePointer de relatar a atividade de toque. |
IMixedRealityTouchHandler |
Observação
IMixedRealityFocusChangedHandler
e IMixedRealityFocusHandler
devem ser tratados nos objetos em que são gerados. É possível receber eventos de foco globalmente, mas, ao contrário de outros eventos de entrada, o manipulador de eventos global não bloqueará o recebimento de eventos com base no foco (o evento será recebido pelo manipulador global e por um objeto correspondente em foco).
Eventos de entrada de ponteiro em ação
Os eventos de entrada de ponteiro são reconhecidos e tratados pelo sistema de entrada MRTK de maneira semelhante aos eventos de entrada regulares. A diferença é que os eventos de entrada de ponteiro são tratados somente pelo GameObject em foco pelo ponteiro que disparou o evento de entrada, bem como por qualquer manipulador de entrada global. Eventos de entrada regulares são tratados por GameObjects em foco para todos os ponteiros ativos.
- O sistema de entrada MRTK reconhece que ocorreu um evento de entrada
- O sistema de entrada MRTK dispara a função de interface relevante para o evento de entrada para todos os manipuladores de entrada globais registrados
- O sistema de entrada determina qual GameObject está em foco para o ponteiro que disparou o evento
- O sistema de entrada utiliza o Sistema de Eventos do Unity para disparar a função de interface relevante para todos os componentes correspondentes no GameObject focado
- Se em algum momento um evento de entrada tiver sido marcado como usado, o processo será encerrado e nenhum GameObjects adicional receberá retornos de chamada.
- Exemplo: componentes que implementam a interface
IMixedRealityFocusHandler
serão pesquisados para obter ganhos do GameObject ou perder o foco - Observação: o Sistema de Eventos do Unity será gerado para pesquisar o GameObject pai se nenhum componente correspondente à interface desejada for encontrado no GameObject atual.
- Exemplo: componentes que implementam a interface
- Se nenhum manipulador de entrada global for registrado e nenhum GameObject for encontrado com um componente/interface correspondente, o sistema de entrada chamará cada manipulador de entrada registrado de fallback
Exemplo
Abaixo está um script de exemplo que altera a cor do renderizador anexado quando um ponteiro tira ou deixa o foco ou quando um ponteiro seleciona o 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;
}
}
Ponteiros de consulta
É possível reunir todos os ponteiros atualmente ativos fazendo loop nas fontes de entrada disponíveis (ou seja, controladores e entradas disponíveis) para descobrir quais ponteiros estão anexados a eles.
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);
}
}
}
Ponteiro principal
Os desenvolvedores podem assinar o evento FocusProviders PrimaryPointerChanged para serem notificados quando o ponteiro principal em foco for alterado. Isso pode ser extremamente útil para identificar se o usuário está interagindo com uma cena por meio de um olhar ou um raio de mão ou outra fonte 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);
}
A PrimaryPointerExample
cena (Assets/MRTK/Examples/Demos/Input/Scenes/PrimaryPointer) mostra como usar os PrimaryPointerChangedHandler
eventos para responder a um novo ponteiro primário.

Resultado do ponteiro
A propriedade pointer Result
contém o resultado atual da consulta de cena usada para determinar o objeto com foco. Para um ponteiro raycast, como os criados por padrão para controladores de movimento, a entrada de foco e os raios manuais, ele conterá o local e o normal da ocorrência do 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);
}
A PointerResultExample
cena (Assets/MRTK/Examples/Demos/Input/Scenes/PointerResult/PointerResultExample.unity) mostra como usar o ponteiro Result
para gerar um objeto no local de ocorrência.

Desabilitar ponteiros
Para habilitar e desabilitar ponteiros (por exemplo, para desabilitar o raio manual), defina o PointerBehavior
para um determinado tipo de ponteiro por meio 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);
}
Veja PointerUtils
e TurnPointersOnOff
para obter mais exemplos.
Interações de ponteiro por meio do editor
Para eventos de ponteiro manipulados por IMixedRealityPointerHandler
, o MRTK fornece mais conveniência na forma do componente, o PointerHandler
que permite que eventos de ponteiro sejam tratados diretamente por meio de Eventos do Unity.

Extensão do ponteiro
Ponteiros distantes têm configurações que limitam o quão longe eles vão raycast e interagem com outros objetos na cena. Por padrão, esse valor é definido como 10 metros. Esse valor foi escolhido para permanecer consistente com o comportamento do shell HoloLens.
Isso pode ser alterado atualizando os DefaultControllerPointer
campos do ShellHandRayPointer
componente pré-fabricado:
Extensão do Ponteiro – isso controla a distância máxima com a qual os ponteiros interagirão.
Extensão de Ponteiro Padrão - Isso controla o comprimento do raio/linha do ponteiro que será renderizado quando o ponteiro não estiver interagindo com nada.