Elemento Interativo [Experimental] — MRTK2
Um ponto de entrada centralizado simplificado para o sistema de entrada MRTK. Contém métodos de gerenciamento de estado, gerenciamento de eventos e a lógica de configuração de estado para estados de interação principal.
O Elemento Interativo é um recurso experimental com suporte no Unity 2019.3 e para cima, pois utiliza uma funcionalidade nova no Unity 2019.3: Serializar Referência.
Inspetor de Elemento Interativo
Durante o modo de reprodução, o Inspetor de Elemento Interativo fornece comentários visuais que indicam se o estado atual está ativo ou não. Se um estado estiver ativo, ele será realçado com uma cor ciano. Se o estado não estiver ativo, a cor não será alterada. Os números ao lado dos estados no inspetor são os valores de estado, se o estado estiver ativo, o valor será 1, se o estado não estiver ativo, o valor será 0.
Estados principais
O Elemento Interativo contém estados principais e dá suporte à adição de estados personalizados. Um estado principal é aquele que já tem a lógica de configuração de estado definida em BaseInteractiveElement
. Veja a seguir uma lista dos estados principais controlados por entrada atuais:
Estados principais atuais
Estados principais de interação próximos e distantes:
Estados principais de interação próxima:
Estados principais de interação distante:
Outros estados principais:
Como adicionar um estado principal por meio do Inspetor
Navegue até Adicionar Estado Principal no inspetor do Elemento Interativo.
Selecione o botão Selecionar Estado para escolher o estado principal a ser adicionado. Os estados no menu são classificados por tipo de interação.
Abra o dobrável Configuração de Eventos para exibir os eventos e as propriedades associadas ao estado.
Como adicionar um estado principal por meio de script
Use o AddNewState(stateName)
método para adicionar um estado principal. Para obter uma lista dos nomes de estado principal disponíveis, use a CoreInteractionState
enumeração .
// Add by name or add by CoreInteractionState enum to string
interactiveElement.AddNewState("SelectFar");
interactiveElement.AddNewState(CoreInteractionState.SelectFar.ToString());
Estrutura interna de estados
Os estados no Elemento Interativo são do tipo InteractionState
. Um InteractionState
contém as seguintes propriedades:
- Nome: o nome do estado.
- Valor: o valor do estado. Se o estado estiver ativado, o valor de estado será 1. Se o estado estiver desativado, o valor do estado será 0.
- Ativo: se o estado está ativo ou não no momento. O valor da propriedade Active é true quando o estado está ativado, false se o estado estiver desativado.
-
Tipo de interação: o tipo de interação de um estado é o tipo de interação para o qual um estado se destina.
-
None
: não dá suporte a nenhuma forma de interação de entrada. -
Near
: suporte de interação próxima. A entrada é considerada quase interação quando uma mão articulada tem contato direto com outro objeto de jogo, ou seja, a posição em que a mão articulada está próxima da posição do objeto de jogo no espaço mundial. -
Far
: suporte à interação distante. A entrada é considerada interação distante quando o contato direto com o objeto de jogo não é necessário. Por exemplo, a entrada por meio do raio do controlador ou do foco é considerada entrada de interação distante. -
NearAndFar
: abrange o suporte de interação próximo e distante. -
Other
: suporte à interação independente de ponteiro.
-
- Configuração de Eventos: a configuração de evento para um estado é o ponto de entrada do perfil de eventos serializados.
Todas essas propriedades são definidas internamente no State Manager
contido no Elemento Interativo. Para modificação de estados, use os seguintes métodos auxiliares:
Métodos auxiliares de configuração de estado
// Get the InteractionState
interactiveElement.GetState("StateName");
// Set a state value to 1/on
interactiveElement.SetStateOn("StateName");
// Set a state value to 0/off
interactiveElement.SetStateOff("StateName");
// Check if a state is present in the state list
interactiveElement.IsStatePresent("StateName");
// Check whether or not a state is active
interactiveElement.IsStateActive("StateName");
// Add a new state to the state list
interactiveElement.AddNewState("StateName");
// Remove a state from the state list
interactiveElement.RemoveState("StateName");
Obter a configuração de evento de um estado é específico para o próprio estado. Cada estado principal tem um tipo de configuração de evento específico que é descrito abaixo nas seções que descrevem cada estado principal.
Aqui está um exemplo generalizado de como obter a configuração de evento de um estado:
// T varies depending on the core state - the specific T's are specified under each of the core state sections
T stateNameEvents = interactiveElement.GetStateEvents<T>("StateName");
Estado padrão
O estado Padrão está sempre presente em um Elemento Interativo. Esse estado estará ativo somente quando todos os outros estados não estiverem ativos. Se qualquer outro estado se tornar ativo, o estado Padrão será definido como desativado internamente.
Um Elemento Interativo é inicializado com os estados Padrão e Foco presentes na lista de estado. O estado Padrão sempre precisa estar presente na lista de estados.
Obtendo eventos de estado padrão
Tipo de configuração de evento para o Estado Padrão: StateEvents
StateEvents defaultEvents = interactiveElement.GetStateEvents<StateEvents>("Default");
defaultEvents.OnStateOn.AddListener(() =>
{
Debug.Log($"{gameObject.name} Default State On");
});
defaultEvents.OnStateOff.AddListener(() =>
{
Debug.Log($"{gameObject.name} Default State Off");
});
Estado de foco
O estado Foco é um estado de interação próximo e distante que pode ser considerado como a realidade misturada equivalente a passar o mouse. O fator diferencial entre interação próxima e distante para o estado Foco é o tipo de ponteiro ativo atual. Se o tipo de ponteiro para o estado foco for o Ponteiro de Cutucada, a interação será considerada quase interação. Se o ponteiro primário não for o Ponteiro de Cutucar, a interação será considerada interação distante. O estado Foco está presente no Elemento Interativo por padrão.
Estado de Foco do Inspetor de Estado
Obtendo eventos de estado de foco
Tipo de configuração de evento para o Estado de Foco: FocusEvents
FocusEvents focusEvents = interactiveElement.GetStateEvents<FocusEvents>("Focus");
focusEvents.OnFocusOn.AddListener((pointerEventData) =>
{
Debug.Log($"{gameObject.name} Focus On");
});
focusEvents.OnFocusOff.AddListener((pointerEventData) =>
{
Debug.Log($"{gameObject.name} Focus Off");
});
Foco próximo versus comportamento distante do foco
Foco próximo ao estado
O estado Foco Próximo é definido quando um evento de foco é acionado e o ponteiro primário é o ponteiro Poke, uma indicação de interação próxima.
Foco Próximo ao
Foco próximo ao foco do inspetor
Obtendo eventos de estado FocusNear
Tipo de configuração de evento para o Estado FocusNear: FocusEvents
FocusEvents focusNearEvents = interactiveElement.GetStateEvents<FocusEvents>("FocusNear");
focusNearEvents.OnFocusOn.AddListener((pointerEventData) =>
{
Debug.Log($"{gameObject.name} Near Interaction Focus On");
});
focusNearEvents.OnFocusOff.AddListener((pointerEventData) =>
{
Debug.Log($"{gameObject.name} Near Interaction Focus Off");
});
Estado de Foco Distante
O estado Focus Far é definido quando o ponteiro primário não é o ponteiro Poke. Por exemplo, o ponteiro de raio do controlador padrão e o ponteiro GGV (Gaze, Gesto, Voz) são considerados ponteiros de interação distantes.
Foco estado
Focus Far State Inspector
Obtendo eventos de estado distante do foco
Tipo de configuração de evento para o Estado FocusFar: FocusEvents
FocusEvents focusFarEvents = interactiveElement.GetStateEvents<FocusEvents>("FocusFar");
focusFarEvents.OnFocusOn.AddListener((pointerEventData) =>
{
Debug.Log($"{gameObject.name} Far Interaction Focus On");
});
focusFarEvents.OnFocusOff.AddListener((pointerEventData) =>
{
Debug.Log($"{gameObject.name} Far Interaction Focus Off");
});
Estado do toque
O estado Touch é um estado de interação próximo que é definido quando uma mão articulada toca o objeto diretamente. Um toque direto significa que o dedo indicador da mão articulada está muito próximo da posição mundial do objeto. Por padrão, um NearInteractionTouchableVolume
componente será anexado ao objeto se o estado Touch for adicionado à lista de estado. A presença de um NearInteractionTouchableVolume
componente ou NearInteractionTouchable
é necessária para detectar eventos touch. A diferença entre NearInteractionTouchableVolume
e NearInteractionTouchable
é que NearInteractionTouchableVolume
detecta um toque com base no colisor do objeto e NearInteractionTouchable
detecta o toque dentro de uma área definida de um plano.
Touch State Behavior
Componente de estado touch do Inspetor de Estado
Obtendo eventos de estado de toque
Tipo de configuração de evento para o Estado de Toque: TouchEvents
TouchEvents touchEvents = interactiveElement.GetStateEvents<TouchEvents>("Touch");
touchEvents.OnTouchStarted.AddListener((touchData) =>
{
Debug.Log($"{gameObject.name} Touch Started");
});
touchEvents.OnTouchCompleted.AddListener((touchData) =>
{
Debug.Log($"{gameObject.name} Touch Completed");
});
touchEvents.OnTouchUpdated.AddListener((touchData) =>
{
Debug.Log($"{gameObject.name} Touch Updated");
});
Selecionar Estado Distante
O estado Selecionar Distante é o IMixedRealityPointerHandler
exibido. Esse estado é um estado de interação distante que detecta um clique de interação distante (air-tap) e mantém o uso de ponteiros de interação distantes, como o ponteiro de raio do controlador padrão ou o ponteiro GGV. O estado Selecionar Distante tem uma opção na dobragem de configuração de evento chamada Global
. Se Global
for true, o IMixedRealityPointerHandler
será registrado como um manipulador de entrada global. O foco em um objeto não será necessário para disparar eventos do sistema de entrada se um manipulador for registrado como global. Por exemplo, se um usuário quiser saber sempre que o gesto de air-tap/select for executado, independentemente do objeto em foco, defina Global
como true.
Selecione Comportamento de Estado Distante
Selecione Inspetor de Estado Distante
Obtendo eventos de estado distante de seleção
Tipo de configuração de evento para o estado SelectFar: SelectFarEvents
SelectFarEvents selectFarEvents = interactiveElement.GetStateEvents<SelectFarEvents>("SelectFar");
selectFarEvents.OnSelectUp.AddListener((pointerEventData) =>
{
Debug.Log($"{gameObject.name} Far Interaction Pointer Up");
});
selectFarEvents.OnSelectDown.AddListener((pointerEventData) =>
{
Debug.Log($"{gameObject.name} Far Interaction Pointer Down");
});
selectFarEvents.OnSelectHold.AddListener((pointerEventData) =>
{
Debug.Log($"{gameObject.name} Far Interaction Pointer Hold");
});
selectFarEvents.OnSelectClicked.AddListener((pointerEventData) =>
{
Debug.Log($"{gameObject.name} Far Interaction Pointer Clicked");
});
Estado clicado
O estado Clicado é disparado por um clique de interação distante (selecionar estado distante) por padrão. Esse estado é ativado internamente, invoca o evento OnClicked e, em seguida, é imediatamente desligado.
Observação
Os comentários visuais no inspetor com base na atividade de estado não estão presentes para o estado Clicado porque ele está ativado e desativado imediatamente.
Estado clicado Comportamento
Clique em Inspetor de Estado
Exemplo de estado de clique próximo e distante
O estado clicado pode ser disparado por meio de pontos de entrada adicionais usando o interactiveElement.TriggerClickedState()
método . Por exemplo, se um usuário quiser um toque de interação próximo para disparar um clique em um objeto também, ele adicionará o TriggerClickedState()
método como um ouvinte no estado de toque.
Obtendo eventos de estado clicado
Tipo de configuração de evento para o Estado Clicado: ClickedEvents
ClickedEvents clickedEvent = interactiveElement.GetStateEvents<ClickedEvents>("Clicked");
clickedEvent.OnClicked.AddListener(() =>
{
Debug.Log($"{gameObject.name} Clicked");
});
Ativar e desativar o estado
Os estados Ativar/Desativar/Desativar são um par e ambos precisam estar presentes para o comportamento de alternância. Por padrão, os estados Ativar/Desativar/Desativar são disparados por meio de um clique de interação distante (selecionar estado Distante). Por padrão, o estado Desativar está ativo ao iniciar, o que significa que a alternância será inicializada para desativada. Se um usuário quiser que o estado Ativar/Desativar esteja ativo na tela inicial, no estado Ativar/Desativar definido IsSelectedOnStart
como true.
Ativar e desativar o comportamento de desativar o comportamento de toggleOn
AlternarOn e Desativar Componente de do Inspetor de Estado no Inspetor
Exemplo de estados de alternância próximos e distantes
Semelhante ao estado Clicked, a configuração de estado de alternância pode ter vários pontos de entrada usando o interactiveElement.SetToggleStates()
método . Por exemplo, se um usuário quiser tocar como um ponto de entrada adicional para definir os estados de alternância, ele adicionará o SetToggleStates()
método a um dos eventos no estado Touch.
Ativando e desativando eventos de estado
Tipo de configuração de evento para o estado ToggleOn: ToggleOnEvents
Tipo de configuração de evento para o estado ToggleOff: ToggleOffEvents
// Toggle On Events
ToggleOnEvents toggleOnEvent = interactiveElement.GetStateEvents<ToggleOnEvents>("ToggleOn");
toggleOnEvent.OnToggleOn.AddListener(() =>
{
Debug.Log($"{gameObject.name} Toggled On");
});
// Toggle Off Events
ToggleOffEvents toggleOffEvent = interactiveElement.GetStateEvents<ToggleOffEvents>("ToggleOff");
toggleOffEvent.OnToggleOff.AddListener(() =>
{
Debug.Log($"{gameObject.name} Toggled Off");
});
Estado da Palavra-chave de Fala
O estado Palavra-chave de Fala escuta as palavras-chave definidas no Perfil de Fala Realidade Misturada. Qualquer novo palavra-chave DEVE ser registrado no perfil de comando de fala antes do runtime (etapas abaixo).
Fala do Comportamento do Estado da Palavra-chave
Componente de palavra-chave de Fala do Inspetor de Estado de Palavra-chave
Observação
O estado Palavra-chave de Fala foi disparado no editor pressionando a tecla F5 no gif acima. A configuração no teste do editor para fala é descrita nas etapas abaixo.
Como registrar um comando/palavra-chave de fala
Selecione o objeto de jogo MixedRealityToolkit
Selecione Copiar e Personalizar o perfil atual
Navegue até a seção Entrada e selecione Clonar para habilitar a modificação do perfil de entrada
Role para baixo até a seção Fala no Perfil de entrada e clone o Perfil de Fala
Selecione Adicionar um Novo Comando de Fala
Insira o novo palavra-chave. Opcional: altere o KeyCode para F5 (ou outro KeyCode) para permitir testes no editor.
Voltar ao inspetor de estado da Palavra-chave de Fala do Elemento Interativo e selecione Adicionar Palavra-chave
Insira o novo palavra-chave que acabou de ser registrado no Perfil de Fala
Para testar o estado da palavra-chave de fala no editor, pressione o KeyCode que foi definido na etapa 6 (F5) para simular a fala palavra-chave evento reconhecido.
Obtendo eventos de estado de palavra-chave de fala
Tipo de configuração de evento para o estado SpeechKeyword: SpeechKeywordEvents
SpeechKeywordEvents speechKeywordEvents = interactiveElement.GetStateEvents<SpeechKeywordEvents>("SpeechKeyword");
speechKeywordEvents.OnAnySpeechKeywordRecognized.AddListener((speechEventData) =>
{
Debug.Log($"{speechEventData.Command.Keyword} recognized");
});
// Get the "Change" Keyword event specifically
KeywordEvent keywordEvent = speechKeywordEvents.Keywords.Find((keyword) => keyword.Keyword == "Change");
keywordEvent.OnKeywordRecognized.AddListener(() =>
{
Debug.Log("Change Keyword Recognized");
});
Estados personalizados
Como criar um estado personalizado por meio do Inspetor
O estado personalizado criado por meio do inspetor será inicializado com a configuração de evento de estado padrão. A configuração de evento padrão para um estado personalizado é do tipo StateEvents
e contém os eventos OnStateOn e OnStateOff.
Navegue até Criar Estado Personalizado no inspetor para Elemento Interativo.
Insira o nome do novo estado. Esse nome deve ser exclusivo e não pode ser o mesmo que os estados principais existentes.
Selecione Definir Nome do Estado para adicionar à lista de estado.
Esse estado personalizado é inicializado com a configuração de evento padrão
StateEvents
que contém osOnStateOn
eventos eOnStateOff
. Para criar uma configuração de evento personalizada para um novo estado, consulte: Criando um estado personalizado com uma configuração de evento personalizada.
Como criar um estado personalizado por meio de script
interactiveElement.AddNewState("MyNewState");
// A new state by default is initialized with a the default StateEvents configuration which contains the
// OnStateOn and OnStateOff events
StateEvents myNewStateEvents = interactiveElement.GetStateEvents<StateEvents>("MyNewState");
myNewStateEvents.OnStateOn.AddListener(() =>
{
Debug.Log($"MyNewState is On");
});
Criando um estado personalizado com uma configuração de evento personalizada
Arquivos de exemplo para um estado personalizado chamado Teclado estão localizados aqui: MRTK\SDK\Experimental\InteractiveElement\Examples\Scripts\CustomStateExample
As etapas a seguir explicam um exemplo existente de criação de uma configuração de evento de estado personalizado e arquivos receptores.
Pense em um nome de estado. Esse nome deve ser exclusivo e não pode ser o mesmo que os estados principais existentes. Para os fins deste exemplo, o nome do estado será Teclado.
Crie dois arquivos .cs chamados state name + "Receiver" e state name + "Events". A nomenclatura desses arquivos é levada em consideração internamente e deve seguir o nome do estado + convenção de evento/receptor.
Consulte os arquivos KeyboardEvents.cs e KeyboardReceiver.cs para obter mais detalhes sobre o conteúdo do arquivo. Novas classes de configuração de evento devem herdar de
BaseInteractionEventConfiguration
e novas classes de receptor de evento devem herdar deBaseEventReceiver
. Exemplos de configuração de estado para o estado teclado estão localizados noCustomStateSettingExample.cs
arquivo .Adicione o estado ao Elemento Interativo usando o nome do estado, o nome do estado será reconhecido se a configuração do evento e os arquivos do receptor de eventos existirem. As propriedades no arquivo de configuração de evento personalizado devem aparecer no inspetor.
Para obter mais exemplos de configuração de eventos e arquivos receptores de eventos, consulte os arquivos nestes caminhos:
- MRTK\SDK\Experimental\InteractiveElement\InteractiveElement\Events\EventConfigurations
- MRTK\SDK\Experimental\InteractiveElement\InteractiveElement\Events\EventReceivers
Cena de exemplo
A cena de exemplo para Elemento Interativo + Visualizador de Estado está localizada aqui: MRTK\SDK\Experimental\InteractiveElement\Examples\InteractiveElementExampleScene.unity
Botão Compactável
A cena de exemplo contém pré-fabricados chamados CompressableButton
e CompressableButtonToggle
, esses pré-fabricados espelho o comportamento dos PressableButtonHoloLens2
botões, que são construídos usando o Elemento Interativo e o Visualizador de Estado.
AtualmenteCompressableButton
, o componente é uma combinação dePressableButtonHoloLens2
PressableButton
+ com BaseInteractiveElement
como uma classe base.
Visualizador de Estado [Experimental]
O componente Visualizador de Estado adiciona animações a um objeto com base nos estados definidos em um componente de Elemento Interativo vinculado. Esse componente cria ativos de animação, coloca-os na pasta MixedRealityToolkit.Generated e habilita a configuração de quadro-chave de animação simplificada por meio da adição de propriedades Animatable a um objeto de jogo de destino. Para habilitar transições de animação entre estados, um ativo controlador de animação é criado e uma máquina de estado padrão é gerada com parâmetros associados e quaisquer transições de estado. O computador de estado pode ser exibido na janela Animador do Unity.
Visualizador de Estado e Sistema de Animação do Unity
Atualmente, o Visualizador de Estado aproveita o Sistema de Animação do Unity.
Quando o botão Gerar Novos Clipes de Animação no Visualizador de Estado é pressionado, novos ativos de clipe de animação são gerados com base nos nomes de estado no Elemento Interativo e são colocados na pasta MixedRealityToolkit.Generated. A propriedade Clipe de Animação em cada contêiner de estado é definida como o clipe de animação associado.
Uma máquina de estado do animador também é gerada para gerenciar transições suaves entre clipes de animação. Por padrão, o computador de estado utiliza o Estado Any para permitir transições entre qualquer estado no Elemento Interativo.
Visualizadores de estado disparados no animador também são gerados para cada estado, os parâmetros de gatilho são usados no Visualizador de Estado para disparar uma animação.
Limitações do Runtime
O Visualizador de Estado deve ser adicionado a um objeto por meio do Inspetor e não pode ser adicionado por meio de script. As propriedades que modificam AnimatorStateMachine/AnimationController estão contidas em um namespace do editor (UnityEditor.Animations
) que é removido quando o aplicativo é criado.
Como usar o Visualizador de Estado
Criar um cubo
Anexar Elemento Interativo
Anexar Visualizador de Estado
Selecione Gerar Novos Clipes de Animação
No contêiner Estado de foco, selecione Adicionar Destino
Arraste o objeto de jogo atual para o campo de destino
Abrir a dobragem propriedades animatable do cubo
Selecione o menu suspenso Da propriedade Animatable e selecione Cor
Selecione Adicionar a Propriedade Animatable de Cor
Escolher uma Cor
Pressione Reproduzir e observe a alteração de cor de transição
Propriedades animáveis
A principal finalidade das Propriedades Animatable é simplificar a configuração do quadro-chave do clipe de animação. Se um usuário estiver familiarizado com o Sistema de Animação do Unity e preferir definir diretamente quadros-chave nos clipes de animação gerados, ele simplesmente não poderá adicionar propriedades Animatable a um objeto de destino e abrir o clipe na janela Animação do Unity (Animação de Animação > do Windows>).
Se estiver usando as propriedades Animatable para animação, o tipo de curva será definido como EaseInOut.
Propriedades animatable atuais:
- Deslocamento de escala
- Deslocamento de posição
- Color
- Cor do sombreador
- Sombreador Float
- Vetor de sombreador
Deslocamento de escala
A propriedade Animatable de Deslocamento de Escala usa a escala atual do objeto e adiciona o deslocamento definido.
Deslocamento de posição
A propriedade Animatable deslocamento de posição assume a posição atual do objeto e adiciona o deslocamento definido.
Cor
A propriedade Color Animatable representará a cor main de um material se o material tiver uma propriedade de cor main. Essa propriedade anima a material._Color
propriedade .
Cor do sombreador
A propriedade Animatable color do sombreador refere-se a uma propriedade de sombreador da cor do tipo. Um nome de propriedade é necessário para todas as propriedades do sombreador. O gif abaixo demonstra a animação de uma propriedade de cor de sombreador chamada Fill_Color que não é a cor do material main. Observe os valores de alteração no inspetor de material.
Sombreador Float
A propriedade Animatable Do Sombreador Float refere-se a uma propriedade de sombreador do tipo float. Um nome de propriedade é necessário para todas as propriedades do sombreador. No gif abaixo, observe os valores de alteração no inspetor de material para a propriedade Metallic.
Vetor de sombreador
A propriedade Animatable do Vetor de Sombreador refere-se a uma propriedade de sombreador do tipo Vector4. Um nome de propriedade é necessário para todas as propriedades do sombreador. No gif abaixo, observe os valores de alteração no inspetor de material para a propriedade Tiling (Main Tex_ST).
Como localizar nomes de propriedades de sombreador anulável
Navegue até Animação de Janela > Animação >
Verifique se o objeto com o Visualizador de Estado está selecionado na hierarquia
Selecione qualquer clipe de animação na janela Animação
Selecione Adicionar Propriedade, abra a dobragem do Renderizador de Malha
Esta lista contém os nomes de todos os nomes de propriedade Animatable