Elemento Interativo [Experimental] — MRTK2
Um ponto de entrada centralizado simplificado para o sistema de entrada MRTK. Contém métodos de gestão de estado, gestão de eventos e a lógica de definição de estado para Estados de Interação Principais.
O Interactive Element é uma funcionalidade experimental suportada no Unity 2019.3 e até à medida que utiliza uma capacidade nova para o Unity 2019.3: Serializar Referência.
Inspetor de Elementos Interativos
Durante o modo de reprodução, o inspetor de Elementos Interativos fornece feedback visual que indica se o estado atual está ou não ativo. Se um estado estiver ativo, será realçado com uma cor de ciano. Se o estado não estiver ativo, a cor não será alterada. Os números junto aos estados no inspetor são os valores de estado, se o estado estiver ativo, o valor é 1, se o estado não estiver ativo, o valor é 0.
Estados Principais
O Elemento Interativo contém estados principais e suporta a adição de estados personalizados. Um estado principal é aquele que já tem a lógica de definição de estado definida em BaseInteractiveElement
. Segue-se uma lista dos estados principais atuais orientados por entrada:
Estados Principais Atuais
Estados Principais de Interação Próxima e Distante:
Estados Principais de Interação Próximos:
Estados Principais de Interação Distantes:
Outros Estados Principais:
Como Adicionar um Estado Principal através do Inspetor
Navegue para Adicionar Estado Principal no inspetor para Elemento Interativo.
Selecione o botão Selecionar Estado para escolher o estado principal a adicionar. Os estados no menu são ordenados por tipo de interação.
Abra a pasta Configuração de Eventos para ver os eventos e propriedades associados ao estado.
Como Adicionar um Estado Principal através de Script
Utilize o AddNewState(stateName)
método para adicionar um estado de núcleo. Para obter uma lista dos nomes de estado principais disponíveis, utilize a enumeração CoreInteractionState
.
// Add by name or add by CoreInteractionState enum to string
interactiveElement.AddNewState("SelectFar");
interactiveElement.AddNewState(CoreInteractionState.SelectFar.ToString());
Estrutura Interna dos 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 de estado. Se o estado estiver ativado, o valor de estado é 1. Se o estado estiver desativado, o valor do estado é 0.
- Ativo: se o estado está ou não ativo. O valor da propriedade Ativo é verdadeiro quando o estado está ativado, falso se o estado estiver desativado.
-
Tipo de Interação: o Tipo de Interação de um estado é o tipo de interação para o que um estado se destina.
-
None
: não suporta qualquer forma de interação de entrada. -
Near
: Suporte de interação próximo. A entrada é considerada quase interação quando uma mão articulada tem contacto 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 de interação distante. A entrada é considerada uma interação muito grande quando o contacto direto com o objeto de jogo não é necessário. Por exemplo, a entrada através do raio do controlador ou do olhar é considerada uma entrada de interação distante. -
NearAndFar
: abrange o suporte de interação próximo e distante. -
Other
: suporte de interação independente do ponteiro.
-
- Configuração do Evento: a configuração do evento para um estado é o ponto de entrada do perfil de eventos serializado.
Todas estas propriedades são definidas internamente no State Manager
elemento contido no Interactive Element. Para modificar estados, utilize os seguintes métodos auxiliares:
State Setting Helper Methods
// 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 eventos de um estado é específico do próprio estado. Cada estado de núcleo tem um tipo de configuração de evento específico que é descrito abaixo nas secções que descrevem cada estado de núcleo.
Eis um exemplo generalizado de como obter a configuração de eventos 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 Predefinido
O estado Predefinido está sempre presente num Elemento Interativo. Este estado só estará ativo quando todos os outros estados não estiverem ativos. Se qualquer outro estado ficar ativo, o estado Predefinido será desativado internamente.
Um Elemento Interativo é inicializado com os estados Predefinido e Foco presentes na lista de estados. O estado Predefinido tem sempre de estar presente na lista de estados.
Obter Eventos de Estado Predefinidos
Tipo de configuração de evento para o Estado Predefinido: 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 Concentração
O Estado de detalhe é um estado de interação próximo e distante que pode ser considerado como a realidade mista equivalente a pairar o rato. O fator de distinção entre interação próxima e distante para o estado de Foco é o tipo de ponteiro ativo atual. Se o tipo de ponteiro para o estado de Foco for o Ponteiro do Toque, a interação é considerada quase interação. Se o ponteiro principal não for o Ponteiro de Picar, a interação é considerada uma interação muito grande. O Estado de detalhe está presente no Elemento Interativo por predefinição.
Estado de Concentração Comportamento
Estado de foco do Inspetor de Estado
Obter Eventos de Estado de Concentração
Tipo de configuração de evento para o Estado de Concentração: 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 vs Comportamento Distante do Foco
Foco Perto do Estado
O estado Foco Próximo é definido quando um evento de foco é elevado e o ponteiro principal é o ponteiro de Poke, uma indicação de interação próxima.
Foco Perto do Comportamento do Estado
Foco Perto do Inspetor de Estado
Obter 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");
});
Foco no Estado Mais Distante
O estado Focus Far é definido quando o ponteiro principal não é o ponteiro Desativar. Por exemplo, o ponteiro de raios do controlador predefinido e o ponteiro GGV (Gaze, Gesture, Voice) são considerados ponteiros de interação distantes.
Focus Far State Behavior
Focus Far State Inspector
Obter 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 do toque é um estado de interação quase definido quando uma mão articulada toca diretamente no objeto. Um toque direto significa que o dedo indicador da mão articulada está muito próximo da posição mundial do objeto. Por predefinição, um NearInteractionTouchableVolume
componente é anexado ao objeto se o estado de Toque for adicionado à lista de estados. A presença de um NearInteractionTouchableVolume
componente ou NearInteractionTouchable
é necessária para detetar eventos táteis. A diferença entre NearInteractionTouchableVolume
e NearInteractionTouchable
é que NearInteractionTouchableVolume
deteta um toque com base no colisor do objeto e NearInteractionTouchable
deteta o toque dentro de uma área definida de um plano.
Touch State Behavior (Estado do Toque) Touch Behavior
Touch State Inspector
Obter Eventos de Estado de Toque
Tipo de configuração de evento para o Estado do 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");
});
Selecione Estado Distante
O estado Selecionar Longe é o IMixedRealityPointerHandler
apresentado. Este estado é um estado de interação distante que deteta um clique de interação distante (toque no ar) e mantém através da utilização de ponteiros de interação distantes, como o ponteiro de raios do controlador predefinido ou o ponteiro GGV. O estado Selecionar Longe tem uma opção na pasta de configuração de eventos denominada Global
. Se Global
for verdadeiro, o IMixedRealityPointerHandler
é registado como um processador de entrada global. O foco num objeto não é necessário para acionar eventos do sistema de entrada se um processador estiver registado como global. Por exemplo, se um utilizador quiser saber sempre que o gesto de toque de ar/seleção é efetuado independentemente do objeto em foco, defina Global
como verdadeiro.
Selecione Comportamento de Estado Distante
Selecione Inspetor de Estado Distante
Obter a opção Selecionar Eventos de Estado Distante
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 é acionado por um clique de interação distante (Selecionar Estado distante) por predefinição. Este estado é ativado internamente, invoca o evento OnClicked e, em seguida, é imediatamente desativado.
Nota
O feedback visual no inspetor com base na atividade de estado não está presente para o estado Clicado porque é ativado e desativado imediatamente.
Comportamento do Estado Clicado Estado
Clique no Componente de
Exemplo de Estado Com Clique Próximo e Distante
O estado clicado pode ser acionado através de pontos de entrada adicionais com o interactiveElement.TriggerClickedState()
método . Por exemplo, se um utilizador quiser um toque de interação quase para acionar um clique num objeto, adicionará o TriggerClickedState()
método como serviço de escuta no estado tátil.
Obter Eventos de Estado Clicados
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 Ativar/Desativar estado
Os estados Ativar/Desativar Ativado e Desativar são um par e ambos têm de estar presentes para o comportamento de alternar. Por predefinição, os estados Ativar e Ativar/Desativar são acionados através de um clique de interação distante (Selecionar Estado distante). Por predefinição, o estado Desativar/Desativar está ativo no início, o que significa que o botão de alternar será inicializado para desativado. Se um utilizador quiser que o estado Ativar/Desativar esteja ativo no início, no estado Ativar/Desativar definido IsSelectedOnStart
como verdadeiro.
Ativar/Desativar/Desativar Comportamento do Estado
Ativar/Desativar/Desativar o componente Inspetor de Estado
Exemplo de Estados Próximos e Distantes
Semelhante ao estado Clicado, a definição de estado de alternar pode ter vários pontos de entrada com o interactiveElement.SetToggleStates()
método . Por exemplo, se um utilizador quiser tocar como um ponto de entrada adicional para definir os estados de alternar, adiciona o SetToggleStates()
método a um dos eventos no estado Tátil.
Ativar/Desativar Eventos de Estado
Tipo de configuração de evento para o Estado Desativar/Desativar: ToggleOnEvents
Tipo de configuração de evento para o Estado Desativado: 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 Voz
O estado palavra-chave de voz escuta as palavras-chave definidas no Perfil de Voz do Mixed Reality. Qualquer nova palavra-chave TEM de ser registada no perfil de comando de voz antes do runtime (passos abaixo).
Palavra-chave Voz do Comportamento do Estado da
Componente de palavra-chave de Voz do Inspetor de Estado da
Nota
O estado da Palavra-chave de Voz foi acionado no editor ao premir a tecla F5 no gif acima. A configuração no teste do editor para voz está descrita nos passos abaixo.
Como Registar um Comando/Palavra-chave de Voz
Selecione o objeto de jogo MixedRealityToolkit
Selecione Copiar e Personalizar o perfil atual
Navegue para a secção Entrada e selecione Clonar para ativar a modificação do Perfil de entrada
Desloque-se para baixo até à secção Voz no Perfil de entrada e clone o Perfil de Voz
Selecione Adicionar um Novo Comando de Voz
Introduza a nova palavra-chave. Opcional: altere o KeyCode para F5 (ou outro KeyCode) para permitir testes no editor.
Voltar ao inspetor de estado da Palavra-chave interactive Element Speech e selecione Adicionar Palavra-chave
Introduza a nova palavra-chave que acabou de ser registada no Perfil de Voz
Para testar o estado da Palavra-chave de Voz no editor, prima o KeyCode que foi definido no passo 6 (F5) para simular o evento reconhecido da palavra-chave de voz.
Obter Eventos de Estado de Palavra-chave de Voz
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 através do Inspetor
O estado personalizado criado através do inspetor será inicializado com a configuração de evento de estado predefinida. A configuração de eventos predefinida para um estado personalizado é do tipo StateEvents
e contém os eventos OnStateOn e OnStateOff.
Navegue para Criar Estado Personalizado no inspetor do Elemento Interativo.
Introduza o nome do novo estado. Este nome tem de ser exclusivo e não pode ser o mesmo que os estados principais existentes.
Selecione Definir Nome do Estado para adicionar à lista de estados.
Este estado personalizado é inicializado com a configuração de evento predefinida
StateEvents
que contém osOnStateOn
eventos eOnStateOff
. Para criar uma configuração de evento personalizada para um novo estado, veja: Criar um Estado Personalizado com uma Configuração de Evento Personalizado.
Como Criar um Estado Personalizado através 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");
});
Criar um Estado Personalizado com uma Configuração de Evento Personalizado
Os ficheiros de exemplo para um estado personalizado com o nome Teclado estão localizados aqui: MRTK\SDK\Experimental\InteractiveElement\Examples\Scripts\CustomStateExample
Os passos seguintes explicam um exemplo existente de criação de ficheiros de recetor e configuração de eventos de estado personalizados.
Pense num nome de estado. Este nome tem de ser exclusivo e não pode ser o mesmo que os estados principais existentes. Para efeitos deste exemplo, o nome do estado será Teclado.
Crie dois ficheiros .cs com o nome state name + "Receiver" e state name + "Events". A nomenclatura destes ficheiros é levada em consideração internamente e tem de seguir a convenção nome do estado + Evento/Recetor.
Consulte os ficheiros KeyboardEvents.cs e KeyboardReceiver.cs para obter mais detalhes sobre os conteúdos dos ficheiros. As novas classes de configuração de eventos têm de herdar de e as novas classes de
BaseInteractionEventConfiguration
recetor de eventos têm de herdar deBaseEventReceiver
. Os exemplos sobre a definição de estado para o Estado do teclado estão localizados noCustomStateSettingExample.cs
ficheiro.Adicione o estado ao Elemento Interativo com o nome do estado. O nome do estado será reconhecido se existirem ficheiros de recetor de eventos e configuração de eventos. As propriedades no ficheiro de configuração de eventos personalizados devem aparecer no inspetor.
Para obter mais exemplos de configuração de eventos e ficheiros de recetor de eventos, veja os ficheiros nestes caminhos:
- MRTK\SDK\Experimental\InteractiveElement\InteractiveElement\Events\EventConfigurations
- MRTK\SDK\Experimental\InteractiveElement\InteractiveElement\Events\EventReceivers
Cenário de Exemplo
A cena de exemplo para Interactive Element + State Visualizer está localizada aqui: MRTK\SDK\Experimental\InteractiveElement\Examples\InteractiveElementExampleScene.unity
Botão Comprimível
A cena de exemplo contém pré-fabricados com o nome CompressableButton
e CompressableButtonToggle
, estas pré-fabs refletem o comportamento dos PressableButtonHoloLens2
botões, que são construídos com o Elemento Interativo e o Visualizador de Estado.
O CompressableButton
componente é atualmente 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 num componente do Elemento Interativo ligado. Este componente cria recursos de animação, coloca-os na pasta MixedRealityToolkit.Generated e permite a definição de keyframe de animação simplificada através da adição de propriedades Animatable a um objeto de jogo de destino. Para ativar transições de animação entre estados, é criado um recurso controlador de animação e é gerado um computador de estado predefinido com parâmetros associados e quaisquer transições de estado. O computador de estado pode ser visualizado na janela Animator do Unity.
State Visualizer and Unity Animation System
Atualmente, o Visualizador de Estado tira partido do Sistema de Animação do Unity.
Quando o botão Gerar Novos Clips de Animação no Visualizador de Estado é premido, são gerados novos recursos de clip de animação com base nos nomes de estado no Elemento Interativo e são colocados na pasta MixedRealityToolkit.Generated. A propriedade Clip de Animação em cada contentor de estado está definida para o clip de animação associado.
Também é gerado um Computador de Estado do Animator para gerir transições suaves entre clips de animação. Por predefinição, o computador de estado utiliza o Estado Qualquer para permitir transições entre qualquer estado no Elemento Interativo.
Os visualizadores de estado acionados no animador também são gerados para cada estado. Os parâmetros do acionador são utilizados no Visualizador de Estado para acionar uma animação.
Limitações do Tempo de Execução
O Visualizador de Estado tem de ser adicionado a um objeto através do Inspetor e não pode ser adicionado através do script. As propriedades que modificam o AnimatorStateMachine/AnimationController estão contidas num espaço de nomes de editor (UnityEditor.Animations
) que é removido quando a aplicação é criada.
Como utilizar o Visualizador de Estado
Criar um Cubo
Anexar Elemento Interativo
Anexar Visualizador de Estado
Selecione Gerar Novos Clips de Animação
No contentor Estado de concentração, selecione Adicionar Destino
Arrastar o objeto de jogo atual para o campo de destino
Abrir a pasta Propriedades da Animatização do Cubo
Selecione o menu pendente da propriedade Animatable e selecione Cor
Selecione Adicionar a Propriedade Animatável de Cor
Escolher uma Cor
Prima reproduzir e observe a alteração da cor transitória
Propriedades Animatable
O principal objetivo das Propriedades Animatable é simplificar a definição de keyframe de clip de animação. Se um utilizador estiver familiarizado com o Sistema de Animação do Unity e preferir definir diretamente keyframes nos clips de animação gerados, simplesmente não pode adicionar propriedades Animatable a um objeto de destino e abrir o clip na janela Animação do Unity (Animação de Animação > do Windows>).
Se utilizar as propriedades Animatable para animação, o tipo de curva está definido como EaseInOut.
Propriedades Animáveis Atuais:
- Deslocamento de Dimensionamento
- Deslocamento da Posição
- Cor
- Cor do Sombreado
- Sombra Flutuante
- Vetor de Sombreado
Deslocamento de Dimensionamento
A propriedade Animatable de Deslocamento de Escala utiliza a escala atual do objeto e adiciona o desvio definido.
Deslocamento da Posição
A propriedade Animatable Desfasamento de Posição assume a posição atual do objeto e adiciona o desvio definido.
Cor
A propriedade Color Animatable representa a cor principal de um material se o material tiver uma propriedade de cor principal. Esta propriedade anima a material._Color
propriedade .
Cor do Sombreado
A propriedade Shader Color Animatable refere-se a uma propriedade shader da cor do tipo. É necessário um nome de propriedade para todas as propriedades de sombreado. O gif abaixo demonstra animar uma propriedade de cor de sombreado chamada Fill_Color que não é a cor material principal. Observe os valores alterados no inspetor de materiais.
Sombra Flutuante
A propriedade Shader Float Animatable refere-se a uma propriedade shader do tipo float. É necessário um nome de propriedade para todas as propriedades de sombreado. No gif abaixo, observe os valores alterados no inspetor de materiais para a propriedade Metalúrgica.
Vetor de Sombreado
A propriedade Shader Vector Animatable refere-se a uma propriedade shader do tipo Vector4. É necessário um nome de propriedade para todas as propriedades de sombreado. No gif abaixo, observe os valores alterados no inspetor de materiais para a propriedade Til (Tex_ST Principal).
How to Find Animatable Shader Property Names
Navegar para Animação de Janela >>
Certifique-se de que o objeto com o Visualizador de Estado está selecionado na hierarquia
Selecionar qualquer clip de animação na janela Animação
Selecione Adicionar Propriedade, abra a pasta Mesh Renderer
Esta lista contém os nomes de todos os nomes de propriedade Animatable