Interagendo — MRTK2

Interagendo

Il Interactable componente è un contenitore all-in-one per rendere qualsiasi oggetto facilmente interagendo e reattivo all'input. Interagendo funge da catch-all per tutti i tipi di input, tra cui tocco, raggi della mano, voce e così via e imbuto queste interazioni in eventi e risposte del tema visivo . Questo componente offre un modo semplice per rendere i pulsanti, modificare il colore sugli oggetti con lo stato attivo e altro ancora.

Come configurare Interactable

Il componente consente tre sezioni principali della configurazione:

  1. Configurazione di input generale
  2. Temi visivi destinati a più GameObject
  3. Gestori eventi

Impostazioni di input generali

Impostazioni generali di interazione

Stati

States è un parametro ScriptableObject che definisce le fasi di interazione, ad esempio stampa o osservata, per Profili e temi visiviinteragendo.

DefaultInteractableStates (Assets/MRTK/SDK/Features/UX/Interactable/States/DefaultInteractableStates.asset) viene fornito con MRTK out-of-box ed è il parametro predefinito per i componenti interagibili.

Esempio di ScriptableObject negli stati nel controllo

L'asset DefaultInteractableStates contiene quattro stati e usa l'implementazione del InteractableStates modello di stato.

  • Impostazione predefinita: non accade nulla, si tratta dello stato di base più isolato.

  • Messa a fuoco: l'oggetto viene puntato. Si tratta di uno stato singolo, non sono attualmente impostati altri stati, ma verrà impostata la classificazione Predefinita.

  • Premere: l'oggetto viene puntato a e viene premuto un pulsante o una mano. Lo stato Di pressione è predefinito e attivo. Questo stato verrà impostato anche come fallback su Pressione fisica.

  • Disabilitato: il pulsante non deve essere interattivo e il feedback visivo informa l'utente se per qualche motivo questo pulsante non è utilizzabile in questo momento. In teoria, lo stato disabilitato potrebbe contenere tutti gli altri stati, ma quando Enabled è disattivato, lo stato Disabilitato prevale su tutti gli altri stati.

Un valore di bit (#) viene assegnato allo stato a seconda dell'ordine nell'elenco.

Nota

È in genere consigliabile usare DefaultInteractableStates (Assets/MRTK/SDK/Features/UX/Interactable/States/DefaultInteractableStates.asset) durante la creazione di componenti interagibili .

Esistono tuttavia 17 stati interagendo che possono essere usati per guidare i temi, anche se alcuni sono progettati per essere guidati da altri componenti. Ecco un elenco di quelli con funzionalità predefinite.

  • Visitato: è stato fatto clic su Interactable.
  • Attiva/Disattiva: il pulsante si trova in uno stato attivato o Indice dimensione è un numero dispari.
  • Movimento: la mano o il controller è stato premuto e si è spostato dalla posizione originale.
  • VoiceCommand: è stato usato un comando vocale per attivare l'oggetto Interactable.
  • PhysicalTouch: viene attualmente rilevato un input tocco, da usare NearInteractionTouchable per abilitare.
  • Afferra: una mano sta attualmente afferrando i limiti dell'oggetto, usare NearInteractionGrabbable per abilitare

Enabled

Attiva o disattiva se un oggetto Interactable verrà attivato o meno. Corrisponde al Interactable.IsEnabled nel codice.

La proprietà enabled di Un oggetto Interactable è diversa dalla proprietà abilitata configurata tramite GameObject/Component (ad esempio SetActive e così via). Se si disabilita GameObject o MonoBehaviour interagibile , tutti gli elementi della classe non verranno eseguiti, inclusi input, temi visivi, eventi e così via. La disabilitazione tramite Interactable.IsEnabled disabilita la maggior parte della gestione dell'input, reimpostando gli stati di input correlati. Tuttavia, la classe eseguirà comunque ogni fotogramma e riceverà eventi di input che verranno ignorati. Ciò è utile per visualizzare l'oggetto Interactable in uno stato disabilitato che può essere eseguito tramite i temi visivi. Un esempio tipico di questo scenario è un pulsante di invio in attesa del completamento di tutti i campi di input necessari.

Azioni di input

Selezionare l'azione di input dal profilo di mapping del controller o della configurazione di input a cui deve rispondere il componente Interactable .

Questa proprietà può essere configurata in fase di esecuzione nel codice tramite Interactable.InputAction.

IsGlobal

Se true, il componente verrà contrassegnato come listener di input globale per l'azione di input selezionata. Il comportamento predefinito è false, che limita l'input solo a questo collisore interagendo/ GameObject.

Questa proprietà può essere configurata in fase di esecuzione nel codice tramite Interactable.IsGlobal.

Comando voce

Comando vocale, dal profilo dei comandi vocali MRTK, per attivare un evento OnClick per l'interazione vocale.

Questa proprietà può essere configurata in fase di esecuzione nel codice tramite Interactable.VoiceCommand.

Richiede lo stato attivo

Se true, il comando vocale attiverà l'oggetto Interactable solo se e solo se ha già lo stato attivo da un puntatore. Se false, Interactable fungerà da listener globale per il comando vocale selezionato. Il comportamento predefinito è true, poiché più listener di riconoscimento vocale globale possono essere difficili da organizzare in una scena.

Questa proprietà può essere configurata in fase di esecuzione nel codice tramite Interactable.VoiceRequiresFocus.

Modalità di selezione

Questa proprietà definisce la logica di selezione. Quando si fa clic su Un oggetto Interactable , l'iterazione viene eseguita in un livello dimensione successivo. Le dimensioni sono simili alla classificazione e definiscono uno stato esterno agli input ,ad esempio lo stato attivo, la pressione e così via. Sono utili per la definizione degli stati di attivazione/disattivazione o di altri stati multi rango associati a un pulsante. Il livello dimensione corrente viene monitorato da Interactable.DimensionIndex.

Le modalità di selezione disponibili sono:

  • Pulsante - Dimensioni = 1, semplice su cui è possibile interagire
  • Passare - Dimensioni = 2, alternative interagendotra/ statodisattivato
  • - Dimensione multiplaDimensioni>= 3, ogni clic aumenta il livello di dimensione corrente + 1. Utile per definire lo stato di un pulsante in un elenco e così via.

L'interazione consente anche di definire più temi per dimensione. Ad esempio, quando SelectionMode=Toggle, è possibile applicare un tema quando l'opzione Interactable viene deselezionata e un altro tema applicato quando viene selezionato il componente.

È possibile eseguire query sulla modalità di selezione corrente in fase di esecuzione tramite Interactable.ButtonMode. È possibile aggiornare la modalità in fase di esecuzione impostando la Interactable.Dimensions proprietà in modo che corrisponda alla funzionalità desiderata. Inoltre, è possibile accedere alla dimensione corrente, utile per le modalità Attiva/ Disattiva e Multidimensionamento , tramite Interactable.CurrentDimension.

Profili interagendo

I profili sono elementi che creano una relazione tra un GameObject e un tema visivo. Il profilo definisce il contenuto che verrà modificato da un tema quando si verifica una modifica dello stato.

I temi funzionano molto come i materiali. Sono oggetti di cui è possibile creare script che contengono un elenco di proprietà che verranno assegnate a un oggetto in base allo stato corrente. I temi possono essere usati di nuovo e possono essere assegnati a più oggetti UX interagendo .

Reimposta in caso di eliminazione definitiva

I temi visivi modificano varie proprietà in un GameObject di destinazione, a seconda della classe e del tipo di motore del tema selezionato. Se Reset On Destroy è true quando il componente Interactable viene eliminato definitivamente, il componente reimposta tutte le proprietà modificate dai temi attivi ai valori originali. In caso contrario, quando viene eliminato definitivamente, il componente Interactable lascerà invariate le proprietà modificate. In questo secondo caso, l'ultimo stato dei valori verrà mantenuto a meno che non venga modificato da un altro componente esterno. Il valore predefinito è false.

Profila le informazioni

evento

Ogni componente interagendo ha un evento OnClick che viene generato quando il componente è semplicemente selezionato. È tuttavia possibile usare Interactable per rilevare eventi di input diversi da Just OnClick.

Fare clic sul pulsante Aggiungi evento per aggiungere un nuovo tipo di definizione del ricevitore di eventi. Dopo l'aggiunta, selezionare il tipo di evento desiderato.

Esempio di eventi)

Esistono diversi tipi di ricevitori di eventi per rispondere a diversi tipi di input. MRTK viene fornito con il seguente set di ricevitori predefiniti.

È possibile creare un ricevitore personalizzato creando una nuova classe che estende ReceiverBase.

Esempio di attivazione/disattivazione dell'evento

Esempio di ricevitore di eventi Toggle

Ricevitori interagendo

Il InteractableReceiver componente consente di definire gli eventi all'esterno del componente interactable di origine. InteractableReceiver sarà in ascolto di un tipo di evento filtrato generato da un altro oggetto Interactable. Se la proprietà Interactable non è assegnata direttamente, la proprietà Search Scope definisce la direzione in cui InteractableReceiver è in ascolto degli eventi che si trovano su se stesso, in un elemento padre o in un GameObject figlio.

InteractableReceiverList agisce in modo simile, ma per un elenco di eventi corrispondenti.

Reciver interagendo

Creare eventi personalizzati

Come i temi visivi, gli eventi possono essere estesi per rilevare qualsiasi modello di stato o per esporre le funzionalità.

Gli eventi personalizzati possono essere creati in due modi principali:

  1. Estendere la ReceiverBase classe per creare un evento personalizzato che verrà visualizzato nell'elenco a discesa dei tipi di evento. Per impostazione predefinita, viene fornito un evento Unity, ma è possibile aggiungere altri eventi unity o l'evento può essere impostato per nascondere gli eventi unity. Questa funzionalità consente a una finestra di progettazione di collaborare con un tecnico in un progetto per creare un evento personalizzato che la finestra di progettazione può configurare nell'editor.

  2. Estendere la ReceiverBaseMonoBehavior classe per creare un componente evento completamente personalizzato che può risiedere nell'oggetto Interactable o in un altro oggetto. Farà ReceiverBaseMonoBehavior riferimento a Interactable per rilevare le modifiche dello stato.

Esempio di estensione ReceiverBase

La CustomInteractablesReceiver classe visualizza informazioni sullo stato di un oggetto Interactable ed è un esempio di come creare un ricevitore di eventi personalizzato.

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

I metodi seguenti sono utili per eseguire l'override/implementazione durante la creazione di un ricevitore di eventi personalizzato. ReceiverBase.OnUpdate() è un metodo astratto che può essere usato per rilevare modelli/transizioni di stato. Inoltre, i ReceiverBase.OnVoiceCommand() metodi e ReceiverBase.OnClick() sono utili per creare logica di evento personalizzata quando viene selezionata l'opzione Interactable .

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
}
Visualizzazione dei campi del ricevitore di eventi personalizzati nel controllo

Gli script ReceiverBase usano InspectorField attributi per esporre proprietà personalizzate nel controllo. Ecco un esempio di Vector3, una proprietà personalizzata con le informazioni sulla descrizione comando e sull'etichetta. Questa proprietà verrà visualizzata come configurabile nel controllo quando viene selezionato un GameObject interagendo e ha aggiunto il tipo di ricevitore di eventi associato.

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

Come usare Interactable

Creazione di un pulsante semplice

È possibile creare un pulsante semplice aggiungendo il componente Interactable a un GameObject configurato per ricevere gli eventi di input. Può avere un collisore su di esso o su un figlio per ricevere l'input. Se si usa Interactable with a Unity UI based GameObjects (Interagire con un gameobject basato sull'interfaccia utente di Unity), deve trovarsi in Canvas GameObject.

Fai un ulteriore passo avanti, creando un nuovo profilo, assegnando il GameObject stesso e creando un nuovo tema. Inoltre, usare l'evento OnClick per fare in modo che si verifichi un evento.

Nota

Per rendere un pulsante premuto è necessario il PressableButton componente . Inoltre, il PhysicalPressEventRouter componente è necessario per incanalare gli eventi di pressione al componente Interactable .

Creazione di pulsanti attiva/disattiva e multidimensionale

Interruttore

Per attivare o disattivare un pulsante, modificare il Selection Mode campo in modo da digitare Toggle. Nella sezione Profili viene aggiunto un nuovo tema attivato/disattivato per ogni profilo utilizzato quando l'opzione Interactable è attivata o disattivata.

SelectionMode Mentre è impostato su Attiva/Disattiva, è possibile utilizzare la casella di controllo IsToggled per impostare il valore predefinito del controllo in fase di inizializzazione in fase di esecuzione.

CanSelect indica che l'elemento Interactable può passare da off a on mentre CanDeselect indica l'inverso.

Esempio di attivazione/disattivazione dei temi visivi del profilo

Gli sviluppatori possono usare le SetToggled interfacce e IsToggled per ottenere/impostare lo stato di attivazione/disattivazione di un oggetto Interactable tramite codice.

// 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;
Attivazione/disattivazione della raccolta dei pulsanti

È comune avere un elenco di pulsanti interruttore in cui solo uno può essere attivo in qualsiasi momento, noto anche come set radiale o pulsanti di opzione e così via.

Usare il InteractableToggleCollection componente per abilitare questa funzionalità. Questo controllo garantisce che un solo elemento Interactable sia attivato in qualsiasi momento. RadialSet (Assets/MRTK/SDK/Features/UX/Interactable/Prefabs/RadialSet.prefab) è anche un ottimo punto di partenza predefinito.

Per creare un gruppo di pulsanti radiali personalizzato:

  1. Creare più gameobject/pulsanti interattivi
  2. Impostare ogni oggetto Interactable with SelectionMode = Toggle, CanSelect = true e CanDeselect = false
  3. Creare un GameObject padre vuoto su tutti gli elementi Interactable e aggiungere il componente InteractableToggleCollection
  4. Aggiungere tutte le interazioni all'oggetto ToggleList nell'oggetto InteractableToggleCollection
  5. Impostare la proprietà InteractableToggleCollection.CurrentIndex per determinare quale pulsante è selezionato per impostazione predefinita all'avvio
Attiva/Disattiva raccolta

Pulsante multidimensionale

La modalità di selezione multidimensionale viene usata per creare pulsanti sequenziali o un pulsante con più di due passaggi, ad esempio il controllo della velocità con tre valori, Fast (1x), Faster (2x) o Fastest (3x).

Con le dimensioni che costituiscono un valore numerico, è possibile aggiungere fino a 9 temi per controllare l'etichetta di testo o la trama del pulsante per ogni impostazione di velocità, usando un tema diverso per ogni passaggio.

Ogni evento click farà avanzare di DimensionIndex 1 in fase di esecuzione fino a quando non viene raggiunto il Dimensions valore. Il ciclo verrà quindi reimpostato su 0.

Esempio di profilo multidimensionale

Gli sviluppatori possono valutare l'oggetto DimensionIndex per determinare quale dimensione è attualmente attiva.

// 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();

Creare l'interazione in fase di esecuzione

L'interazione può essere facilmente aggiunta a qualsiasi GameObject in fase di esecuzione. Nell'esempio seguente viene illustrato come assegnare un profilo con un tema visivo.

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()

Eventi interagendo tramite codice

È possibile aggiungere un'azione all'evento di base Interactable.OnClick tramite codice con l'esempio seguente.

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

Usare la Interactable.AddReceiver<T>() funzione per aggiungere ricevitori di eventi in modo dinamico in fase di esecuzione.

Il codice di esempio seguente illustra come aggiungere un oggetto InteractableOnFocusReceiver, che è in ascolto dell'immissione/uscita dello stato attivo e, inoltre, definire il codice azione da eseguire quando vengono attivate le istanze dell'evento.

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"));
}

Il codice di esempio riportato di seguito illustra come aggiungere un oggetto InteractableOnToggleReceiver, in ascolto delle transizioni di stato selezionate/deselezionate nelle transizioni di stato abilitate per l'interazione attiva e definisce inoltre il codice azione da eseguire quando vengono attivate le istanze dell'evento.

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"));
}

Vedi anche