Interactable — MRTK2

Avec interaction

Le Interactable composant est un conteneur tout-en-un qui permet de rendre n’importe quel objet facilement interagissant et réactif à l’entrée. Interactable agit comme un fourre-tout pour tous les types d’entrée, y compris l’interaction tactile, les rayons de la main, la parole, etc. et canalise ces interactions dans des événements et des réponses au thème visuel . Ce composant offre un moyen simple de créer des boutons, de modifier la couleur des objets avec le focus, etc.

Guide pratique pour configurer Interactable

Le composant permet trois sections principales de la configuration :

  1. Configuration générale des entrées
  2. Thèmes visuels ciblés sur plusieurs GameObjects
  3. Gestionnaires d’événements

Paramètres d’entrée généraux

Paramètres généraux interagissants

États

States est un paramètre ScriptableObject qui définit les phases d’interaction, telles que l’appui ou l’observation, pour les profils interagissants et les thèmes visuels.

DefaultInteractableStates (Assets/MRTK/SDK/Features/UX/Interactable/States/DefaultInteractableStates.asset) est fourni avec MRTK out-of-box et est le paramètre par défaut pour les composants interactables.

Exemple d’états ScriptableObject dans l’inspecteur

La ressource DefaultInteractableStates contient quatre états et utilise l’implémentation du modèle d’état InteractableStates .

  • Par défaut : rien ne se passe, il s’agit de l’état de base le plus isolé.

  • Focus : l’objet est pointé vers. Il s’agit d’un état unique, aucun autre état n’est actuellement défini, mais il sera classé par défaut.

  • Appuyez sur : l’objet est pointé vers et un bouton ou une main appuie. L’état Appuye ne classe pas Par défaut et Focus. Cet état est également défini comme secours sur l’appui physique.

  • Désactivé : le bouton ne doit pas être interactif et les commentaires visuels indiquent à l’utilisateur si, pour une raison quelconque, ce bouton n’est pas utilisable pour le moment. En théorie, l’état désactivé peut contenir tous les autres états, mais quand Activé est désactivé, l’état Désactivé l’emporte sur tous les autres états.

Une valeur de bit (#) est affectée à l’état en fonction de l’ordre dans la liste.

Notes

Il est généralement recommandé d’utiliser DefaultInteractableStates (Assets/MRTK/SDK/Features/UX/Interactable/States/DefaultInteractableStates.asset) lors de la création de composants interactables .

Toutefois, il existe 17 états interactables disponibles qui peuvent être utilisés pour piloter des thèmes, bien que certains soient destinés à être pilotés par d’autres composants. Voici la liste de ceux qui ont des fonctionnalités intégrées.

  • Visité : l’élément Interactable a été cliqué.
  • Bascule : le bouton est dans un état basculé ou l’index de dimension est un nombre impair.
  • Geste : la main ou le contrôleur a été appuyé et a été déplacé à partir de la position d’origine.
  • VoiceCommand : une commande vocale a été utilisée pour déclencher l’élément Interactable.
  • PhysicalTouch : une entrée tactile est actuellement détectée, à utiliser NearInteractionTouchable pour activer.
  • Saisir : une main est en train de saisir dans les limites de l’objet, utilisez NearInteractionGrabbable pour activer

Activé

Indique si l’option Interactable démarre activée ou non. Cela correspond au dans le Interactable.IsEnabled code.

La propriété activée d’un interactable est différente de la propriété activée configurée via GameObject/Component (par exemple, SetActive, etc.). La désactivation du GameObject ou du MonoBehaviour interactable désactive l’exécution de tous les éléments de la classe, y compris les entrées, les thèmes visuels, les événements, etc. La désactivation de via Interactable.IsEnabled désactive la plupart de la gestion des entrées, en réinitialisant les états d’entrée associés. Toutefois, la classe exécute toujours chaque frame et reçoit des événements d’entrée qui seront ignorés. Cela est utile pour afficher l’élément Interactable dans un état désactivé, ce qui peut être effectué via des thèmes visuels. Par exemple, un bouton d’envoi attend que tous les champs d’entrée requis soient renseignés.

Actions d’entrée

Sélectionnez l’action d’entrée dans la configuration d’entrée ou le profil de mappage du contrôleur auquel le composant Interactable doit réagir.

Cette propriété peut être configurée au moment de l’exécution dans le code via Interactable.InputAction.

IsGlobal

Si la valeur est true, cela marque le composant en tant qu’écouteur d’entrée global pour l’action d’entrée sélectionnée. Le comportement par défaut est false, ce qui limite l’entrée à ce collider/GameObject interactable .

Cette propriété peut être configurée au moment de l’exécution dans le code via Interactable.IsGlobal.

Commande Speech

Commande vocale, à partir du profil de commandes vocales MRTK, pour déclencher un événement OnClick pour l’interaction vocale.

Cette propriété peut être configurée au moment de l’exécution dans le code via Interactable.VoiceCommand.

Nécessite le focus

Si la valeur est true, la commande vocale active l’élément Interactable uniquement si et seulement s’il a déjà le focus à partir d’un pointeur. Si la valeur est false, l’élément Interactable agit en tant qu’écouteur global pour la commande vocale sélectionnée. Le comportement par défaut est vrai, car plusieurs écouteurs vocaux globaux peuvent être difficiles à organiser dans une scène.

Cette propriété peut être configurée au moment de l’exécution dans le code via Interactable.VoiceRequiresFocus.

Mode de sélection

Cette propriété définit la logique de sélection. Lorsque l’utilisateur clique sur un élément Interactable , il effectue une itération dans un niveau de dimension suivant. Les dimensions sont similaires au classement et définissent un état en dehors des entrées (par exemple, focus, appui, etc.). Ils sont utiles pour définir des états bascule ou d’autres états à plusieurs classements associés à un bouton. Le niveau de dimension actuel est suivi par Interactable.DimensionIndex.

Les modes de sélection disponibles sont les suivants :

  • Bouton - Dimensions = 1, interactionnable simple cliquable
  • Bascule - Dimensions = 2, alternatives interagissantes entre l’état désactivé/
  • Dimension multiple - Dimensions>= 3, chaque clic augmente le niveau de dimension actuel + 1. Utile pour définir un état de bouton pour une liste, etc.

Interactable permet également de définir plusieurs thèmes par dimension. Par exemple, lorsque SelectionMode=Toggle, un thème peut être appliqué lorsque l’élément Interactable est désélectionné et un autre thème appliqué lorsque le composant est sélectionné.

Le mode de sélection actuel peut être interrogé au moment de l’exécution via Interactable.ButtonMode. Vous pouvez mettre à jour le mode au moment de l’exécution en définissant la Interactable.Dimensions propriété pour qu’elle corresponde à la fonctionnalité souhaitée. En outre, la dimension actuelle, utile pour les modes Bascule et Multi-Dimension , est accessible via Interactable.CurrentDimension.

Profils interagissants

Les profils sont des éléments qui créent une relation entre un GameObject et un thème visuel. Le profil définit le contenu qui sera manipulé par un thème lorsqu’un changement d’état se produit.

Les thèmes fonctionnent beaucoup comme les matériaux. Il s’agit d’objets scriptables qui contiennent une liste de propriétés qui seront affectées à un objet en fonction de l’état actuel. Les thèmes sont également réutilisables et peuvent être attribués sur plusieurs objets d’expérience utilisateur interagissants .

Réinitialiser lors de la destruction

Les thèmes visuels modifient différentes propriétés sur un GameObject ciblé, en fonction de la classe et du type de moteur de thème sélectionnés. Si Réinitialiser à la destruction a la valeur true lorsque le composant Interactable est détruit, le composant réinitialise toutes les propriétés modifiées des thèmes actifs à leurs valeurs d’origine. Sinon, lorsqu’il est détruit, le composant Interactable laisse les propriétés modifiées telles quelles. Dans ce dernier cas, le dernier état des valeurs persiste, sauf s’il est modifié par un autre composant externe. La valeur par défaut est false.

Profiler les theams

Événements

Chaque composant interactable a un événement OnClick qui se déclenche lorsque le composant est simplement sélectionné. Toutefois, Interactable peut être utilisé pour détecter des événements d’entrée autres que simplement OnClick.

Cliquez sur le bouton Ajouter un événement pour ajouter un nouveau type de définition de récepteur d’événements. Une fois ajouté, sélectionnez le type d’événement souhaité.

Exemple d’événements)

Il existe différents types de récepteurs d’événements pour répondre à différents types d’entrée. MRTK est fourni avec l’ensemble de récepteurs prêt à l’emploi suivant.

Un récepteur personnalisé peut être créé en créant une nouvelle classe qui étend ReceiverBase.

Exemple de récepteur toggle d’événement

Exemple de récepteur d’événements toggle

Récepteurs interagissants

Le InteractableReceiver composant permet de définir des événements en dehors du composant interactable source. InteractableReceiver écoute un type d’événement filtré déclenché par un autre interactable. Si la propriété Interactable n’est pas directement affectée, la propriété Étendue de recherche définit la direction dans laquelle InteractableReceiver écoute les événements qui se trouvent sur lui-même, dans un parent ou dans un GameObject enfant.

InteractableReceiverList agit de la même manière, mais pour une liste d’événements correspondants.

Requête interagissante

Créer des événements personnalisés

Comme les thèmes visuels, les événements peuvent être étendus pour détecter n’importe quel modèle d’état ou pour exposer des fonctionnalités.

Les événements personnalisés peuvent être créés de deux manières main :

  1. Étendez la ReceiverBase classe pour créer un événement personnalisé qui apparaîtra dans la liste déroulante des types d’événements. Un événement Unity est fourni par défaut, mais des événements Unity supplémentaires peuvent être ajoutés ou l’événement peut être défini pour masquer les événements Unity. Cette fonctionnalité permet à un concepteur de travailler avec un ingénieur sur un projet pour créer un événement personnalisé que le concepteur peut configurer dans l’éditeur.

  2. Étendez la ReceiverBaseMonoBehavior classe pour créer un composant d’événement entièrement personnalisé qui peut résider sur l’objet Interactable ou un autre objet. le ReceiverBaseMonoBehavior référencera l’élément Interactable pour détecter les changements d’état.

Exemple d’extension ReceiverBase

La CustomInteractablesReceiver classe affiche status informations sur un objet Interactable et est un exemple de création d’un récepteur d’événements personnalisé.

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

Les méthodes suivantes sont utiles pour remplacer/implémenter lors de la création d’un récepteur d’événements personnalisé. ReceiverBase.OnUpdate() est une méthode abstraite qui peut être utilisée pour détecter des modèles/transitions d’état. En outre, les ReceiverBase.OnVoiceCommand() méthodes et ReceiverBase.OnClick() sont utiles pour créer une logique d’événement personnalisée lorsque interactable est sélectionné.

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
}
Affichage des champs de récepteur d’événements personnalisés dans l’inspecteur

Les scripts ReceiverBase utilisent InspectorField des attributs pour exposer des propriétés personnalisées dans l’inspecteur. Voici un exemple de Vector3, une propriété personnalisée avec des informations d’info-bulle et d’étiquette. Cette propriété s’affiche comme configurable dans l’inspecteur lorsqu’un GameObject interagissant est sélectionné et que le type de récepteur d’événements associé est ajouté.

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

Guide pratique pour utiliser Interactable

Création d’un bouton simple

Vous pouvez créer un bouton simple en ajoutant le composant Interactable à un GameObject configuré pour recevoir des événements d’entrée. Il peut y avoir un collider sur celui-ci ou sur un enfant pour recevoir une entrée. Si vous utilisez Interactable avec un GameObjects basé sur l’interface utilisateur Unity, il doit se trouver sous l’objet Canvas GameObject.

Pour aller plus loin, créez un profil, affectez le GameObject lui-même et créez un nouveau thème. En outre, utilisez l’événement OnClick pour faire en sorte que quelque chose se produise.

Notes

Pour qu’un bouton soit enfoncé , le composant est nécessaire PressableButton . En outre, le PhysicalPressEventRouter composant est nécessaire pour diriger les événements de presse vers le composant Interactable .

Création de boutons bascule et multidimensionnel

Bouton bascule

Pour rendre un bouton bascule, remplacez le Selection Mode champ par le type Toggle. Dans la section Profils , un nouveau thème bascule est ajouté pour chaque profil utilisé lorsque l’option Interactable est activée.

Bien que le SelectionMode ait la valeur Toggle, la zone IsToggled case activée peut être utilisée pour définir la valeur par défaut du contrôle lors de l’initialisation de l’exécution.

CanSelect signifie que l’élément Interactable peut aller de off à on , tandis que CanDeselect signifie l’inverse.

Exemple de thèmes visuels bascules de profil

Les développeurs peuvent utiliser les SetToggled interfaces et IsToggled pour obtenir/définir l’état bascule d’un objet Interactable via du code.

// 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;
Activer/désactiver la collection de boutons

Il est courant d’avoir une liste de boutons bascule où un seul peut être actif à un moment donné, également appelé jeu radial ou case d’option, etc.

Utilisez le InteractableToggleCollection composant pour activer cette fonctionnalité. Ce contrôle garantit qu’un seul interactable est activé à un moment donné. Le RadialSet (Assets/MRTK/SDK/Features/UX/Interactable/Prefabs/RadialSet.prefab) est également un excellent point de départ.

Pour créer un groupe de boutons radial personnalisés :

  1. Créer plusieurs gameobjects/boutons interagissants
  2. Définissez chaque interactable avec SelectionMode = Toggle, CanSelect = true et CanDeselect = false
  3. Créez un GameObject parent vide sur tous les interactables et ajoutez le composant InteractableToggleCollection
  4. Ajouter tous les éléments Interactables à toggleList sur InteractableToggleCollection
  5. Définissez la propriété InteractableToggleCollection.CurrentIndex pour déterminer le bouton sélectionné par défaut au début
Activer/désactiver la collection

Bouton multidimensionnel

Le mode de sélection multidimensionnel est utilisé pour créer des boutons séquentiels, ou un bouton qui comporte plus de deux étapes, comme le contrôle de la vitesse avec trois valeurs, Fast (1x), Faster (2x) ou Faster (3x).

Les dimensions étant une valeur numérique, jusqu’à 9 thèmes peuvent être ajoutés pour contrôler l’étiquette de texte ou la texture du bouton pour chaque paramètre de vitesse, en utilisant un thème différent pour chaque étape.

Chaque événement de clic avance le DimensionIndex de 1 au moment de l’exécution jusqu’à ce que la Dimensions valeur soit atteinte. Ensuite, le cycle est réinitialisé à 0.

Exemple de profil multidimensionnel

Les développeurs peuvent évaluer pour DimensionIndex déterminer quelle dimension est actuellement active.

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

Créer une interaction au moment de l’exécution

L’interaction peut être facilement ajoutée à n’importe quel GameObject au moment de l’exécution. L’exemple suivant montre comment affecter un profil avec un thème visuel.

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

Événements interagissants via du code

Vous pouvez ajouter une action à l’événement de base Interactable.OnClick via du code avec l’exemple suivant.

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

Utilisez la Interactable.AddReceiver<T>() fonction pour ajouter dynamiquement des récepteurs d’événements au moment de l’exécution.

L’exemple de code ci-dessous montre comment ajouter un interactableOnFocusReceiver, qui écoute l’entrée/sortie du focus, et définit en outre le code d’action à exécuter lorsque les instances d’événement se déclenchent.

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

L’exemple de code ci-dessous montre comment ajouter un interactableOnToggleReceiver, qui écoute les transitions d’état sélectionné/désélectionné sur les interactables pouvant être activés, et définit en outre le code d’action à effectuer lorsque les instances d’événement se déclenchent.

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

Voir aussi