Menu manual — MRTK3

Menu de Mãos

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.

Cena de exemplo do menu manual

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.

Exemplo de menu manual grande 1

Configuração do Palm Up

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.

Exemplo de menu manual grande 2

Por fim, o botão fechar precisa reativar o SolverHandler.UpdateSolvers para restaurar a funcionalidade do solucionador HandConstraint.

Exemplo de menu manual grande 3

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 no HandConstraintSolver, de LookAtTrackedObject para LookAtMainCamera como o GazeAlignment ângulo com o solucionador varia.

Zona segura de exemplo de menu manual

  • 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 exclusivos HandConstraint .

    • 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 o SolverHandlervalor de 's UpdateSolver 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).
    • 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.
  • Lógica de reanexamento: atualmente, o HandConstraintPalmUp pode reanexar automaticamente o objeto de destino ao ponto rastreado, independentemente de o SolverHandler's UpdateSolver ser True. Isso é feito chamando a HandConstraintPalmUpfunção 's StartWorldLockReattachCheckCoroutine() depois de ter sido bloqueada pelo mundo (que, nesse caso, está efetivamente definindo o UpdateSolver do SolverHandler como False).