Arquitetura do Interagente – MRTK3
O MRTK se baseia no conjunto de interatores oferecido pelo Kit de Ferramentas de Interação XR do Unity. Recursos de realidade misturada, como acompanhamento articulado da mão, foco e pinçagem, exigem interatores mais elaborados do que o conjunto fornecido com XRI por padrão. O MRTK define novas interfaces de interator, categorizadas geralmente pela modalidade de entrada e implementações correspondentes.
Resumo e Revisão
Para desenvolvedores iniciantes no XRI, é recomendável examinar primeiro a Documentação de arquitetura do XRI do Unity. Os interatores do MRTK são subclasses de interatores do XRI existentes ou implementações das interfaces do interator do XRI. Consulte a documentação do Unity sobre a arquitetura do interagente que também se aplica ao MRTK.
Bons cidadãos de XRI
Os interatores personalizados do MRTK são bem comportados em relação às interfaces do interator do XRI padrão; da perspectiva dos sistemas de XRI, eles são indistinguíveis de interatores de "baunilha". O inverso também é verdadeiro; ao criar interacionáveis avançadas no MRTK, os interatores do XRI padrão ainda funcionarão para focalização e seleção básicas. Faz parte do esforço do MRTK ser totalmente compatível com projetos de XRI existentes. Se você tiver um aplicativo do XRI, as interacionáveis do MRTK e os controles de interface do usuário funcionarão com a configuração de XRI "baunilha" existente.
Abstração da modalidade de entrada
O dispositivo de entrada, o interator que executa a interação e os eventos de interação gerados são todos isolados de arquitetura no XRI. Esse isolamento é fundamental para a estratégia de abstração de entrada no MRTK3 e nos permite gravar interações entre plataformas e entre dispositivos que funcionam bem em todos os contextos.
Do MRTK v2, há um instinto comum para interações de código específicas de um determinado tipo de entrada ou dispositivo. Muitos desenvolvedores estão acostumados a escrever interações que reagem especificamente a uma captura próxima, a um raio distante ou a algum outro tipo de entrada específico.
Embora o MRTK3 ainda permita a desambiguação e a detecção de modos de entrada individuais, as interações de codificação rígida para tipos de entrada individuais específicos são artificialmente limitadas e reduzem a flexibilidade de suas interações. Mais informações sobre isso podem ser encontradas na documentação de arquitetura interacionável, mas a chave para os interatores é que eles geralmente não precisam mapear 1:1 com dispositivos de entrada.
AttachTransform e Inversão de Controle
Muito do que o MRTK v2 fez em "mover lógicas" como parte do ObjectManipulator
,Slider
e assim por diante, agora é responsabilidade do próprio interagente. O interator agora controla seu attachTransform para definir como um tipo específico de manipulação se comporta. Não é mais necessário escrever lógica de interação complexa no interativo que difere entre as modalidades de entrada. Em vez disso, sua lógica de manipulação unificada pode escutar a pose do attachTransform
, independentemente da modalidade de entrada ou do dispositivo que a conduz.
Por exemplo, um GrabInteractor
's attachTransform
está localizado no ponto de captura na mão/controlador. Um XRRayInteractor
's attachTransform
está localizado no ponto de ocorrência no final do raio. Os CanvasProxyInteractor
's attachTransform
estão localizados onde quer que o mouse tenha clicado. Para todos esses diferentes interagentes, o interativo não precisa se importar com o tipo de interagente para responder adequadamente às manipulações.
O interativo consulta o attachTransform
e pode tratar todos os mesmos attachTransform
, independentemente do tipo de interagente.
Essa abordagem é essencial para a compatibilidade com os interagentes do XRI existentes, bem como para revisão futura de suas interações para modalidades de entrada que ainda não foram desenvolvidas. Se um novo método de entrada for introduzido, você não precisará alterar os interacionáveis existentes se o novo interator gerar um válido e bem comportado attachTransform
.
Assim, filosoficamente, a attachTransform
é a lógica da interação. Para quaisquer interações personalizadas, sempre prefira escrever um novo interagente com uma nova lógica attachTransform
em vez de regravar ou estender interativos para serem personalizados para sua nova interação. Dessa forma, todos os interacionáveis existentes podem aproveitar os benefícios de sua nova interação, em vez de apenas os que você regravou ou estendeu.
XRControllers e Associação de Entrada
A maioria dos interatores não associa diretamente às ações de entrada. A maioria deriva de XRBaseControllerInteractor
, o que requer um XRController
interator acima na hierarquia. As associações XRController
às ações de entrada e, em seguida, propagam as ações relevantes (selecione, assim por diante) para todos os interagentes anexados.
No entanto, alguns interatores podem precisar de associações de entrada especiais ou entradas adicionais que não forneçam XRController
. Nesses casos, os interatores têm a opção de associar diretamente às suas próprias ações de entrada exclusivas ou até mesmo usar outras fontes sem Sistema de Entrada para lógica de interação. As classes base XRI preferem escutar as associações dos XRController
's, mas esses comportamentos podem ser substituídos para usar fontes de entrada externas ou alternativas.
Interfaces
XRI define o básico IXRInteractor
, IXRHoverInteractor
, IXRSelectInteractor
e IXRActivateInteractor
. O MRTK define interfaces adicionais para os interatores. Alguns expõem informações adicionais sobre interações específicas do MRTK e outras simplesmente para categorização e identificação. Essas interfaces estão todas localizadas no pacote Core, enquanto as implementações residem em outros pacotes, incluindo Entrada.
Importante
Embora essas interfaces sejam úteis se você precisar filtrar um tipo específico de interação, é recomendável que você não codifique suas interações para escutar essas interfaces especificamente. Em todas as situações, sempre prefira o isSelected de XRI genérico e isHovered, em vez de qualquer interface específica à interação.
A menos que seja necessário, você não deve fazer referência às implementações concretas do MRTK dessas interfaces em interativos, a menos que seja absolutamente necessário. Em todos os casos, é preferível referenciar as interfaces. Referenciar explicitamente os tipos concretos restringirá seus interacionáveis para trabalhar apenas com os tipos atuais e existentes. Fazendo referência apenas às interfaces, você garante a compatibilidade com implementações futuras que podem não subclasse as implementações existentes.
IVariableSelectInteractor
Os interatores que implementam essa interface podem emitir a seleção de variável (ou seja, analógica) para interacionáveis. A quantidade de seleção de variável pode ser consultada com a propriedade SelectProgress
. Os interatores do MRTK que implementam essa interface incluem o MRTKRayInteractor
e GazePinchInteractor
. Os interativos básicos (os interativos padrão XRI e MRTKBaseInteractable
) não serão afetados pela quantidade de seleção variável, StatefulInteractable
, no entanto, ouve esse valor e calcula-o Selectedness
com base max()
em todos os interagentes de variáveis e não variáveis participantes.
IGazeInteractor
Os interatores que implementam essa interface representam o olhar passivo do usuário, separados de qualquer manipulação ou intenção. A implementação do MRTK é FuzzyGazeInteractor
, que herda do XRI XRRayInteractor
, e adiciona lógica de conversão de cone difusa. XRBaseInteractable
sinalizará IsGazeHovered
quando um IGazeInteractor
focalizador estiver pairando.
IGrabInteractor
Os interatores que implementam essa interface representam uma interação física de captura de campo próximo. O attachTransform
é definido como o ponto de captura. A implementação do MRTK é GrabInteractor
, que subclassifica XRDirectInteractor
do XRI.
IPokeInteractor
Os interatores que implementam essa interface representam uma interação de cutucar. Observe que isso não implica necessariamente um dedo! Os interatores arbitrários podem implementar essa interface e oferecer interações de cutucar de fontes que não são dedos. Em uma das poucas instâncias em que verificar as interfaces do interagente é uma boa ideia, interagentes como PressableButton
escutar IPokeInteractor
, especificamente, para impulsionar a pressão volumétrica. Qualquer interator que implementa IPokeInteractor
induzirá pressionamentos 3D nos botões.
IPokeInteractor
expõe a propriedade PokeRadius
, que define as características do objeto de cutucar. O cutucar é considerado centralizado no attachTransform
e estende-se para fora do attachTransform
por PokeRadius
. Interacionáveis como PressableButton
compensar a distância de push 3D por esse raio, que pode ser controlado pela espessura do dedo físico do usuário no caso de pressionamentos baseados em dedos.
A implementação do MRTK dessa interface é PokeInteractor
. Em nosso projeto modelo, nós também fornecemos outro exemplo de um IPokeInteractor
que não é conduzido por dedos, o PenInteractor
fornece interações de cutucar enraizadas na ponta de um estilete 3D virtual.
IRayInteractor
Os interatores que implementam essa interface representam uma interação de apontamento baseada em raios. O attachTransform
representa o local de ocorrência do raio na superfície do objeto de destino durante uma seleção.
A implementação do MRTK dessa interface é MRTKRayInteractor
, herdar diretamente do XRI XRRayInteractor
.
Observação
O XRI XRRayInteractor
não implementa essa interface MRTK.
ISpeechInteractor
Os interatores que implementam essa interface representam interações orientadas por fala. A implementação do MRTK é SpeechInteractor
.
O MRTK SpeechInteractor
, internamente, usa PhraseRecognitionSubsystem
e assina eventos de registro interativos do XRI XRInteractionManager
. No entanto, os interativos não precisam se preocupar com qual subsistema está executando o processamento de fala; ISpeechInteractor
s geram os mesmos eventos XRI (selecione etc.) que qualquer outro interagente faz.
IGazePinchInteractor
Essa interface é simplesmente uma especialização da interface IVariableSelectInteractor
. Os interatores que implementam essa interface são, implicitamente, interatores de seleção de variáveis. IGazePinchInteractor
s representam expressamente uma manipulação remota direcionada indiretamente. Um interator baseado em foco separado direciona o destino da interação, e a manipulação é por uma mão ou um controlador. O attachTransform
se comporta da mesma maneira que um attachTransform
do IRayInteractor
faz, ele se ajusta ao ponto de ocorrência no destino quando uma seleção é iniciada.
Quando vários IGazePinchInteractor
s participam de uma única interação, seus attachTransform
s são deslocados pelo deslocamento do ponto mediano entre todos os pontos de pinçamento participantes. Assim, os interacionáveis podem interpretá-los attachTransform
da mesma maneira que fariam para qualquer outra interação com várias mãos, como as attachTransforms
interações de captura ou interações de raio.
A implementação do MRTK é o GazePinchInteractor
.
IHandedInteractor
Alguns interagents podem optar por implementar a interface IHandedInteractor
para especificar explicitamente que estão associados a uma mão específica em um usuário. Alguns interatores não estão associados à entrega e, portanto, não implementam isso. Os exemplos mais óbvios seriam como SpeechInteractor
ou FuzzyGazeInteractor
.
Os interatores do MRTK que implementam essa interface são o HandJointInteractor
, um genérico, abstrato XRDirectInteractor
controlado por uma articulação de mão arbitrária, o GazePinchInteractor
e o MRTKRayInteractor
.
Atualmente, os interativos usam essa interface para disparar determinados efeitos quando selecionados que precisam desambiguar entre uma mão esquerda ou direita. O exemplo mais notável disso é o efeito de pulso na biblioteca de componentes do UX.