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, o attachTransformé a lógica de 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; ISpeechInteractors 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. IGazePinchInteractors 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 IGazePinchInteractors participam de uma única interação, seus attachTransforms são deslocados pelo deslocamento do ponto mediano entre todos os pontos de pinçamento participantes. Assim, os interacionáveis podem interpretá-los attachTransformda 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.