Menu manual — MRTK3
Os menus de mão permitem que os usuários tragam a interface do usuário anexada à mão para funções usadas com frequência. Geralmente, são pequenos grupos de botões que oferecem ações rápidas. No entanto, às vezes, layouts mais complexos para exibir informações ou configurações são fornecidos ao usuário como um menu de mão, muitas vezes com a opção de "remover" o menu da mão e ancorá-lo no mundo.
O menu Mão fornece as opções "Exigir Mão Simples" e "Usar Ativação de Foco" para evitar a ativação falsa ao interagir com outros objetos. É recomendável usar essas opções para evitar a ativação indesejada.
Cena de exemplo e Prefabs
Se você estiver usando o projeto de modelo, HandMenuExamples.unity
demonstrará várias configurações comuns para menus de mão, todas usando o HandConstraintPalmUp
script.
HandMenuLarge
Essa pré-fabricado demonstra o exemplo de uma interface do usuário grande ou complexa que requer tempo de interação estendido. Para esse tipo de interface do usuário, é recomendável bloquear o menu na queda manual para melhorar a usabilidade e evitar a fadiga do braço. Este exemplo também dá suporte a 'grab and pull' para bloquear o menu.
Neste exemplo, o menu torna-se visível e invisível ativando o objeto MenuContent no evento OnFirstHandDetected(). Com o evento OnLastHandLost(), o botão fechar é ativado e a animação de posicionamento é disparada. A animação é uma flutuação de dimensionamento simples. Como não ocultamos o evento MenuContent em OnLastHandLost(), o menu será bloqueado automaticamente quando a mão não estiver visível. Os valores na seção Palm Up foram otimizados para tornar o menu bloqueado mundialmente sem serem arrastados muito para baixo na queda manual.
Este exemplo fornece a barra agarrável na área inferior do menu e o comportamento de bloqueio automático do mundo. O usuário pode desanexar explicitamente o menu da mão e colocá-lo no mundo, agarrando-o. Para conseguir isso, no evento ManipulationStarted() em ObjectManipulator, desabilitamos SolverHandler.UpdateSolvers. Caso contrário, o menu não poderá ser desanexado, pois o solucionador HandConstraint tentará posicionar o menu perto da posição da mão. Também usamos HandConstraintPalmUp.StartWorldLockReattachCheckCoroutine para permitir que o usuário levante a mão para reanexar o menu à mão.
Por fim, o botão fechar precisa reativar o SolverHandler.UpdateSolvers para restaurar a funcionalidade do solucionador HandConstraint.
Scripts
O comportamento HandConstraint
fornece um solucionador que restringe o objeto controlado a uma região segura para conteúdo restrito à mão (como interface do usuário da mão, menus etc.). Regiões seguras são consideradas áreas que não se cruzam com a mão. Uma classe derivada de HandConstraint
chamada HandConstraintPalmUp
também é incluída para demonstrar um comportamento comum de ativar o objeto controlado pelo solucionador quando a palma da mão estiver voltada para o usuário.
Confira as dicas de ferramenta disponíveis para cada HandConstraint
propriedade para obter documentação adicional. Algumas propriedades são definidas em mais detalhes abaixo.
Zona segura: a zona segura especifica onde, na mão, para restringir o conteúdo. É recomendável que o conteúdo seja colocado no Lado ulnar para evitar a sobreposição com a mão e melhor qualidade de interação. Zonas seguras são calculadas pela orientação das mãos projetadas em um plano ortogonal para a exibição da câmera e raycasting contra uma caixa delimitadora ao redor das mãos. Zonas seguras são definidas para trabalhar com
XRNode
. É recomendável explorar o que cada zona segura representa em diferentes tipos de controlador.Siga a mão até a câmera de frente Com isso ativo, o solucionador seguirá a rotação manual até que o menu esteja suficientemente alinhado com o foco quando ele enfrentar a câmera. Para fazer isso funcionar, altere o
SolverRotationBehavior
noHandConstraintSolver
, deLookAtTrackedObject
paraLookAtMainCamera
como oGazeAlignment
ângulo com o solucionador varia.
Eventos de ativação: atualmente, o
HandConstraint
dispara quatro eventos de ativação. Esses eventos podem ser usados em muitas combinações diferentes para criar comportamentos exclusivosHandConstraint
.- OnHandActivate: dispara quando uma mão atende ao método IsHandActive.
- OnHandDeactivate: dispara quando o método IsHandActive não é mais atendido.
- OnFirstHandDetected: ocorre quando o estado de acompanhamento da mão muda de nenhuma mão na exibição para a primeira mão na exibição.
- OnLastHandLost: ocorre quando o estado de acompanhamento manual muda de pelo menos uma mão na exibição para nenhuma mão na exibição.
Lógica de Ativação/Desativação do Solver: atualmente, a recomendação para ativar e desativar
HandConstraintPalmUp
a lógica é fazer isso usando oSolverHandler
valor de 'sUpdateSolver
em vez de desabilitar/habilitar o objeto. Isso pode ser visto na cena de exemplo por meio dos ganchos baseados no editor disparados após os eventos ManipulationHandler "OnManipulationStarted/Ended" do menu anexado.-
Parando a lógica de restrição manual: ao tentar definir o objeto restrito à mão para parar (e não executar a lógica de ativação/desativação), defina UpdateSolver como False em vez de desabilitar HandConstraintPalmUp.
- Se você quiser habilitar a lógica de reanexamento baseada em foco (ou mesmo não baseada em foco), isso é seguido por chamar a
HandConstraintPalmUp.StartWorldLockReattachCheckCoroutine()
função. Isso disparará uma corrotina que continuará a marcar se os critérios "IsValidController
" forem atendidos e definirá UpdateSolver como True quando ele for (ou o objeto estiver desabilitado).
- Se você quiser habilitar a lógica de reanexamento baseada em foco (ou mesmo não baseada em foco), isso é seguido por chamar a
- Iniciando a lógica de restrição manual: ao tentar definir o objeto restrito à mão para começar a seguir sua mão novamente (com base em se ele atende aos critérios de ativação), defina UpdateSolver do SolverHandler como true.
-
Parando a lógica de restrição manual: ao tentar definir o objeto restrito à mão para parar (e não executar a lógica de ativação/desativação), defina UpdateSolver como False em vez de desabilitar HandConstraintPalmUp.
-
Lógica de reanexamento: atualmente, o
HandConstraintPalmUp
pode reanexar automaticamente o objeto de destino ao ponto rastreado, independentemente de oSolverHandler
'sUpdateSolver
ser True. Isso é feito chamando aHandConstraintPalmUp
função 'sStartWorldLockReattachCheckCoroutine()
depois de ter sido bloqueada pelo mundo (que, nesse caso, está efetivamente definindo o UpdateSolver do SolverHandler como False).