Interagivel

Interagivel

O Interactable componente é um recipiente tudo-em-um para tornar qualquer objeto facilmente Interactable e responsivo à entrada. Atua interagidos como um catch-all para todos os tipos de entradas, incluindo toque, raios de mão, fala, etc. e funil essas interações em eventos e respostas temáticas visuais. Este componente fornece uma maneira fácil de fazer botões, mudar de cor em objetos com foco, e muito mais.

Como configurar interagindo

O componente permite três secções primárias de configuração:

  1. Configuração geral de entrada
  2. Temas visuais direcionados contra vários GameObjects
  3. Processadores de eventos

Definições gerais de entrada

Definições Interagivel Geral

Estados

Estados é um parâmetro ScriptableObject que define as fases de interações, como a imprensa ou observada, para perfis interagiáveis e temas visuais.

Os Estados DefaultInteractable States (Ativos/MRTK/SDK/Features/UX/Interactable/States/DefaultInteractableStates.asset) com mrtk fora de caixa e é o parâmetro padrão para componentes interagiáveis.

Estados ScriptableObject exemplo em inspetor

O ativo DefaultInteractableStates contém quatro estados e utiliza a implementação do modelo de estado.

  • Padrão:Nada está a acontecer, este é o estado base mais isolado.

  • Foco: O objeto está a ser apontado. Este é um único estado, nenhum outro estado está atualmente definido, mas irá sair da classificação Padrão.

  • Pressione: O objeto está a ser apontado e um botão ou mão está a premir. O Estado de Imprensa exclui as fileiras Default e Focus. Este estado também será definido como uma reversão para a Imprensa Física.

  • Desativado: O botão não deve ser interativo e o feedback visual informará o utilizador se, por alguma razão, este botão não for utilizável neste momento. Em teoria, o estado de deficientes poderia conter todos os outros estados, mas quando o Enabled é desligado, o estado deficiente supera todos os outros estados.

Um pouco de valor (#) é atribuído ao estado dependendo da ordem na lista.

Nota

É geralmente recomendado utilizar os Estados DefaultInteractable States (Ativos/MRTK/SDK/Features/UX/UX/States/DefaultInteractableStates.asset) ao criar componentes interagiáveis.

No entanto, existem 17 Estados interagiáveis disponíveis que podem ser usados para impulsionar temas, embora alguns sejam destinados a ser conduzidos por outros componentes. Aqui está uma lista de pessoas com funcionalidade incorporada.

  • Visitado: o Interactível foi clicado.
  • Toggled: O botão está num estado alternado ou o índice de dimensão é um número ímpar.
  • Gesto: A mão ou controlador foi pressionado e saiu da posição original.
  • VoiceCommand: Um comando de fala foi usado para desencadear o Interactível.
  • PhysicalTouch: Uma entrada de toque é detetada atualmente, utilização NearInteractionTouchable para ativar.
  • Grab: Uma mão está atualmente agarrada nos limites do objeto, use NearInteractionGrabbable para ativar

Ativado

Alterna se um Interactível começará ativado ou não. Isto corresponde ao Interactable.IsEnabled código in.

A propriedade ativada de um Interingable é diferente da propriedade ativada configurada via GameObject/Component (i.e SetActive etc). Desativar o GameObject ou MonoBehaviour interativamente irá desativar tudo na classe de correr, incluindo entradas, temas visuais, eventos, etc. A desativação através de um tratamento desactivadorá a maioria do manuseamento de entradas, repondo estados de entrada relacionados. No entanto, a classe continuará a executar todos os quadros e receberá eventos de entrada que serão ignorados. Isto é útil para exibir o Interactível num estado desativado que pode ser feito através de Temas Visuais. Um exemplo típico disso seria um botão de submissão à espera que todos os campos de entrada necessários fossem concluídos.

Ações de entrada

Selecione a ação de entrada a partir da configuração de entrada ou perfil de mapeamento do controlador ao que o componente Interactível deve reagir.

Esta propriedade pode ser configurada em tempo de execução em código via Interactable.InputAction .

IsGlobal

Se for verdade, isto marcará o componente como um ouvinte de entrada global para a ação de entradaselecionada . O comportamento predefinido é falso, o que irá restringir a entrada apenas a este collider/GameObject interagivel.

Esta propriedade pode ser configurada em tempo de execução em código via Interactable.IsGlobal .

Comando da Fala

Comando defala , do Perfil de Comandos de Discurso mrtk, para desencadear um evento OnClick para interação de voz.

Esta propriedade pode ser configurada em tempo de execução em código via Interactable.VoiceCommand .

Requer foco

Se for verdade, o comando de voz só ativará o Interactível se e somente se já tiver foco a partir de um ponteiro. Se for falso, então o Interactable atuará como um ouvinte global para o comando de voz selecionado. O comportamento padrão é verdadeiro, pois vários ouvintes globais podem ser difíceis de organizar numa cena.

Esta propriedade pode ser configurada em tempo de execução em código via Interactable.VoiceRequiresFocus .

Modo de seleção

Esta propriedade define a lógica de seleção. Quando um Interactível é clicado, itera para um nível de dimensão seguinte. As dimensões são semelhantes à classificação e definem um estado fora das entradas (isto é, foco, imprensa etc). São úteis para definir estados toggle ou outros estados multi-rank associados a um botão. O nível atual de dimensão é rastreado por Interactable.DimensionIndex .

Os modos de seleção disponíveis são:

  • BotãoDimensões = 1, simples clicável interagiável
  • ToggleDimensões = 2, Alterna entreestadooff
  • MultidimensionamentoDimensões = 3, cada clique aumenta o nível de dimensão atual + 1. Útil para definir um estado de botão para uma lista, etc.

Interagindo também permite que vários temas sejam definidos por dimensão. Por exemplo, quando o SelectionMode=Toggle,um tema pode ser aplicado quando o Interactível é desselecionado e outro tema aplicado quando o componente é selecionado.

O modo de seleção atual pode ser consultado no tempo de funcionamento através de Interactable.ButtonMode . A atualização do modo no tempo de execução pode ser conseguida definindo a Interactable.Dimensions propriedade para corresponder à funcionalidade desejada. Além disso, a dimensão atual, útil para os modos Toggle e Multi-Dimension, pode ser acedida através de .

Perfis interagiáveis

Os perfis são itens que criam uma relação entre um GameObject e um Tema Visual. O perfil define que conteúdo será manipulado por um tema quando ocorre uma mudança de estado.

Os temas funcionam muito como materiais. São objetos scriptable que contêm uma lista de propriedades que serão atribuídas a um objeto baseado no estado atual. Os temas também são reutilizáveis e podem ser atribuídos através de vários objetos UX interagiáveis.

Reset na destruição

Os temas visuais modificam várias propriedades num GameObject direcionado, dependendo da classe e tipo de motor temático selecionado. Se o reset on destroy for verdadeiro quando o componente interactível for destruído, o componente irá redefinir todas as propriedades modificadas de temas ativos para os seus valores originais. Caso contrário, quando destruído, o componente Interactível deixará quaisquer propriedades modificadas como está. Neste último caso, o último estado de valores persistirá a menos que seja alterado por outro componente externo. O padrão é falso.

Theams de perfil

Eventos

Cada componente interagivel tem um evento OnClick que dispara quando o componente é simplesmente selecionado. No entanto, o Interactable pode ser utilizado para detetar eventos de entrada que não apenas o OnClick.

Clique no botão Adicionar Evento para adicionar um novo tipo de definição de Recetor de Evento. Uma vez adicionado, selecione o tipo de Evento desejado.

Exemplo de eventos)

Existem diferentes tipos de recetores de eventos para responder a diferentes tipos de entrada. Os navios MRTK com o seguinte conjunto de recetores fora de caixa.

Um recetor personalizado pode ser criado fazendo uma nova classe que se estende ReceiverBase .

Exemplo do recetor de toggle do evento

Exemplo de um recetor de evento toggle

Recetores interagiáveis

O InteractableReceiver componente permite que os eventos sejam definidos fora da componente InteractableReceiver de origem. O InteractableReceiver ouvirá um tipo de evento filtrado disparado por outro Interactable. Se a propriedade interagiável não for diretamente atribuída, então a propriedade Search Scope define a direção que o InteractableReceiver ouve para eventos que são sobre si mesmo, em um pai, ou em uma criança GameObject.

InteractableReceiverList atua de forma semelhante, mas para uma lista de eventos correspondentes.

Reciver interagivel

Criar eventos personalizados

Tal como os Temas Visuais,os eventos podem ser estendidos para detetar qualquer padrão de estado ou para expor a funcionalidade.

Os eventos personalizados podem ser criados de duas formas principais:

  1. Estenda a ReceiverBase classe para criar um evento personalizado que aparecerá na lista de tipos de eventos. Um evento de Unidade é fornecido por padrão, mas eventos adicionais de Unidade podem ser adicionados ou o evento pode ser configurado para esconder eventos de Unidade. Esta funcionalidade permite que um designer trabalhe com um engenheiro num projeto para criar um evento personalizado que o designer possa configurar no editor.

  2. Estenda a ReceiverBaseMonoBehavior classe para criar um componente de evento completamente personalizado que possa residir no Objeto ReceiverBaseMonoBehavior ou outro. O ReceiverBaseMonoBehavior testamento refere o ReceiverBaseMonoBehavior para detetar alterações de estado.

Exemplo de extensão ReceiverBase

A CustomInteractablesReceiver classe apresenta informações sobre o estado de um CustomInteractablesReceiver e é um exemplo de como criar um Recetor de Eventos personalizado.

public CustomInteractablesReceiver(UnityEvent ev) : base(ev, "CustomEvent")
{
    HideUnityEvents = true; // hides Unity events in the receiver - meant to be code only
}

Os seguintes métodos são úteis para substituir/implementar ao criar um recetor de eventos personalizado. ReceiverBase.OnUpdate() é um método abstrato que pode ser usado para detetar padrões/transições do estado. Além disso, os ReceiverBase.OnVoiceCommand() métodos e ReceiverBase.OnClick() métodos são úteis para criar lógica de evento personalizado quando o ReceiverBase.OnVoiceCommand() é selecionado.

public override void OnUpdate(InteractableStates state, Interactable source)
{
    if (state.CurrentState() != lastState)
    {
        // the state has changed, do something new
        lastState = state.CurrentState();
        ...
    }
}

public virtual void OnVoiceCommand(InteractableStates state, Interactable source,
                                    string command, int index = 0, int length = 1)
{
    base.OnVoiceCommand(state, source, command, index, length);
    // voice command called, perform some action
}  

public virtual void OnClick(InteractableStates state,
                            Interactable source,
                            IMixedRealityPointer pointer = null)
{
    base.OnClick(state, source);
    // click called, perform some action
}
Exibindo campos de recetores de eventos personalizados no inspetor

Os scripts receiverBase usam atributos para expor propriedades personalizadas no inspetor. Aqui está um exemplo de Vetor3, uma propriedade personalizada com informação de etiqueta de ferramentas e etiqueta. Esta propriedade aparecerá como configurável no inspetor quando um GameObject interagivel for selecionado e tiver o tipo de Recetor de Eventos associado adicionado.

[InspectorField(Label = "<Property label>",Tooltip = "<Insert tooltip info>",Type = InspectorField.FieldTypes.Vector3)]
public Vector3 EffectOffset = Vector3.zero;

Como usar interagiável

Construindo um botão simples

Pode-se criar um botão simples adicionando o componente Interável a um GameObject configurado para receber eventos de entrada. Pode ter um colisor nele ou numa criança para receber a entrada. Se utilizar o Interactable com um GameObjects baseado em UI de unidade, deve estar sob o Canvas GameObject.

Leve o botão um passo mais além, criando um novo perfil, atribuindo o próprio GameObject e criando um novo tema. Além disso, use o evento OnClick para fazer algo acontecer.

Nota

Fazer um botão pressável requer o componente. Além disso, o PhysicalPressEventRouter componente é necessário para funilizar eventos de pressão para o componente PhysicalPressEventRouter

Criação de botões de alternância e multi-dimensões

Botão de toggle

Para fazer um botão Toggle-able, altere o Selection Mode campo para escrever Toggle . Na secção Perfis, é adicionado um novo tema alternado para cada perfil que é utilizado quando o Interactível é alternado.

Enquanto a SelectionMode é definida para Toggle, a caixa de verificação SelectionMode pode ser usada para definir o valor padrão do controlo na inicialização do tempo de execução.

CanSelect significa que o Interactível pode ir de um lado para o outro enquanto o CanDeselect significa o inverso.

Exemplo de temas visuais de perfil Toggle

Os desenvolvedores podem utilizar as SetToggled interfaces e IsToggled para obter/definir o estado de alternância de um SetToggled via código.

// If using SelectionMode = Toggle (i.e Dimensions == 2)

// Make the Interactable selected and toggled on
myInteractable.IsToggled = true;

// Get whether the Interactable is selected or not
bool isSelected = myInteractable.IsToggled;
Coleção de botões toggle

É comum ter uma lista de botões de alternância onde apenas um pode estar ativo em qualquer momento, também conhecido como um conjunto radial ou botões de rádio etc.

Utilize o InteractableToggleCollection componente para ativar esta funcionalidade. Este controlo garante que apenas um inter-interactível é ligado a qualquer momento. O RadialSet (Ativos/MRTK/SDK/Features/UX/Interactable/Prefabs/RadialSet.prefab) é também um excelente ponto de partida fora da caixa.

Para criar um grupo de botões radiais personalizados:

  1. Criar vários GameObjects/botões interagiáveis
  2. Definir cada interagido com SelectionMode = Toggle, CanSelect = verdadeiro, e CanDeselect = falso
  3. Crie um GameObject parental vazio sobre todos os Interáveis e adicione o componente InteractableToggleCollection
  4. Adicione todos os Interagiáveis à Lista de Alternância na InteractableToggleCollection
  5. Defina a propriedade InteractableToggleCollection.CurrentIndex para determinar qual o botão selecionado por padrão no início
Coleção Toggle

Botão multidimensional

O modo de seleção multidimensional é utilizado para criar botões sequenciais, ou um botão que tenha mais de dois passos, como controlar a velocidade com três valores, Fast (1x), Faster (2x) ou Fast (3x).

Sendo as dimensões um valor numérico, podem ser adicionados até 9 temas para controlar a etiqueta de texto ou textura do botão para cada regulação de velocidade, utilizando um tema diferente para cada passo.

Cada evento de clique irá adiantar o DimensionIndex por 1 no tempo de execução até que o Dimensions valor seja atingido. Em seguida, o ciclo será reiniciado para 0.

Exemplo de perfil multidimensional

Os desenvolvedores podem avaliar DimensionIndex a dimensão atualmente ativa.

// If using SelectionMode = Multi-dimension (i.e Dimensions >= 3)

//Access the current DimensionIndex
int currentDimension = myInteractable.CurrentDimension;

//Set the current DimensionIndex to 2
myInteractable.CurrentDimension = 2;

// Promote Dimension to next level
myInteractable.IncreaseDimension();

Criar Interagiável no tempo de execução

Interagindo pode ser facilmente adicionado a qualquer GameObject em tempo de execução. O exemplo a seguir demonstra como atribuir um perfil com um tema visual.

var interactableObject = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
var interactable = interactableObject.AddComponent<Interactable>();

// Get the default configuration for the Theme engine InteractableColorTheme
var newThemeType = ThemeDefinition.GetDefaultThemeDefinition<InteractableColorTheme>().Value;

// Define a color for every state in our Default Interactable States
newThemeType.StateProperties[0].Values = new List<ThemePropertyValue>()
{
    new ThemePropertyValue() { Color = Color.black},  // Default
    new ThemePropertyValue() { Color = Color.black}, // Focus
    new ThemePropertyValue() { Color = Random.ColorHSV()},   // Pressed
    new ThemePropertyValue() { Color = Color.black},   // Disabled
};

interactable.Profiles = new List<InteractableProfileItem>()
{
    new InteractableProfileItem()
    {
        Themes = new List<Theme>()
        {
            Interactable.GetDefaultThemeAsset(new List<ThemeDefinition>() { newThemeType })
        },
        Target = interactableObject,
    },
};

// Force the Interactable to be clicked
interactable.TriggerOnClick()

Eventos interagiáveis via código

Pode-se adicionar uma ação ao evento base Interactable.OnClick através de código com o seguinte exemplo.

public static void AddOnClick(Interactable interactable)
{
    interactable.OnClick.AddListener(() => Debug.Log("Interactable clicked"));
}

Utilize a Interactable.AddReceiver<T>() função para adicionar os recetores de eventos dinamicamente no tempo de execução.

O código de exemplo abaixo demonstra como adicionar um InteractableOnFocusReceiver, que ouve a entrada/saída de foco, e além disso define o código de ação para executar quando as instâncias do evento dispararem.

public static void AddFocusEvents(Interactable interactable)
{
    var onFocusReceiver = interactable.AddReceiver<InteractableOnFocusReceiver>();

    onFocusReceiver.OnFocusOn.AddListener(() => Debug.Log("Focus on"));
    onFocusReceiver.OnFocusOff.AddListener(() => Debug.Log("Focus off"));
}

O código de exemplo abaixo demonstra como adicionar um InteractableOnToggleReceiver, que ouve transições estatais selecionadas/desescolhadas em Interáveis com recurso a alternáveis, e define ainda código de ação para executar quando as instâncias do evento disparam.

public static void AddToggleEvents(Interactable interactable)
{
    var toggleReceiver = interactable.AddReceiver<InteractableOnToggleReceiver>();

    // Make the interactable have toggle capability, from code.
    // In the gui editor it's much easier
    interactable.Dimensions = 2;
    interactable.CanSelect = true;
    interactable.CanDeselect  = true;

    toggleReceiver.OnSelect.AddListener(() => Debug.Log("Toggle selected"));
    toggleReceiver.OnDeselect.AddListener(() => Debug.Log("Toggle un-selected"));
}

Ver também