Pointeurs — MRTK2

Pointer

Cet article explique comment configurer et répondre aux entrées de pointeur dans la pratique. Pour mieux comprendre comment contrôler plusieurs pointeurs à un niveau élevé, consultez Architecture du pointeur.

Les pointeurs sont générés automatiquement au moment de l’exécution lorsqu’un nouveau contrôleur est détecté. Plusieurs pointeurs peuvent être attachés à un contrôleur. Par exemple, avec le profil de pointeur par défaut, Windows Mixed Reality contrôleurs obtiennent respectivement une ligne et un pointeur parabolique pour la sélection normale et la téléportation.

Configuration du pointeur

Les pointeurs sont configurés dans le cadre du système d’entrée dans MRTK via un MixedRealityPointerProfile. Ce type de profil est affecté à un MixedRealityInputSystemProfile inspecteur de configuration MRTK. Le profil pointeur détermine le curseur, les types de pointeurs disponibles au moment de l’exécution et la façon dont ces pointeurs communiquent entre eux pour déterminer celui qui est actif.

  • Étendue pointant : définit la distance maximale pour laquelle un pointeur peut interagir avec un GameObject.

  • Pointage de masques de couche Raycast : il s’agit d’un tableau hiérarchisé de LayerMasks pour déterminer les objets GameObject possibles avec lesquels un pointeur donné peut interagir et l’ordre d’interaction à tenter. Cela peut être utile pour garantir que les pointeurs interagissent d’abord avec les éléments de l’interface utilisateur avant d’autres objets de scène. Pointer Profile Example

Configuration des options de pointeur

La configuration du profil de pointeur MRTK par défaut inclut les classes de pointeur suivantes et les préfabriqués associés prêtes à l’emploi. La liste des pointeurs disponibles pour le système au moment de l’exécution est définie sous Options de pointeur dans le profil pointeur. Les développeurs peuvent utiliser cette liste pour reconfigurer les pointeurs existants, ajouter de nouveaux pointeurs ou en supprimer un.

Pointer Options Profile Example

Chaque entrée pointeur est définie par l’ensemble de données suivant :

  • Type de contrôleur : ensemble de contrôleurs pour lequel un pointeur est valide.

    • Par exemple, pokePointer est responsable des objets « poking » avec un doigt et est, par défaut, marqué comme prenant uniquement en charge le type de contrôleur de main articulé. Les pointeurs sont instanciés uniquement lorsqu’un contrôleur devient disponible et, en particulier, le type de contrôleur définit les contrôleurs que ce prefab de pointeur peut être créé avec.
  • Remise : permet à un pointeur d’être instancié uniquement pour une main spécifique (gauche/droite)

Notes

La définition de la propriété Handedness d’une entrée pointeur sur None le désactive efficacement du système comme alternative à la suppression de ce pointeur de la liste.

  • Pointeur Prefab : cette ressource de préfabriqué est instanciée lorsqu’un contrôleur correspondant au type de contrôleur spécifié et à la remise commence à être suivi.

Il est possible d’avoir plusieurs pointeurs associés à un contrôleur. Par exemple, dans DefaultHoloLens2InputSystemProfile (Assets/MRTK/SDK/Profiles/HoloLens2/) le contrôleur de main articulé est associé à PokePointer, GrabPointer et DefaultControllerPointer (c’est-à-dire les rayons de main).

Notes

MRTK fournit un ensemble de préfabriqués de pointeur dans Assets/MRTK/SDK/Features/UX/Prefabs/Pointers. Un nouveau préfabriqué personnalisé peut être créé tant qu’il contient l’un des scripts de pointeur dans Assets/MRTK/SDK/Features/UX/Scripts/Pointers ou tout autre script implémentant IMixedRealityPointer.

Configuration du curseur

Le curseur de regard est directement configurable via la GazeCursorPrefab propriété dans l’éditeur MixedRealityInputSystemProfile . Pour configurer le curseur utilisé pour d’autres pointeurs, vous devez modifier le préfabriqué utilisé dans le CursorPrefab champ du .BaseControllerPointer Pour modifier le curseur par programmation, modifiez la BaseCursor propriété sur le comportement correspondant IMixedRealityPointer .

Cursor Prefab Property

Consultez nos préfabriqués de curseur dans Assets/MRTK/SDK/Features/UX/Prefabs/Cursors pour obtenir des exemples d’implémentations de comportement du curseur. En particulier, DefaultGazeCursor offre une implémentation robuste de la modification du graphique du curseur en fonction de l’état contextuel.

Classes de pointeur par défaut

Les classes suivantes sont les pointeurs MRTK prêtes à l’emploi disponibles et définies dans le profil de pointeur MRTK par défaut décrit ci-dessus. Chaque préfabriqué de pointeur fourni sous Assets/MRTK/SDK/Features/UX/Prefabs/Pointers contient l’un des composants pointeurs attachés.

MRTK Default Pointers

Pointeurs lointains

LinePointer

LinePointer, une classe de pointeur de base, dessine une ligne à partir de la source de l’entrée (c’est-à-dire le contrôleur) dans la direction du pointeur et prend en charge un seul cast de rayons dans cette direction. En règle générale, les classes enfants telles que les ShellHandRayPointer pointeurs de téléport sont instanciés et utilisés (qui dessinent également des lignes pour indiquer à quel endroit la téléportation se terminera) au lieu de cette classe qui fournit principalement des fonctionnalités courantes.

Pour les contrôleurs de mouvement comme dans Tableaux, Vive et Windows Mixed Reality, la rotation correspond à la rotation du contrôleur. Pour d’autres contrôleurs comme HoloLens 2 mains articulées, la rotation correspond à la pose pointante fournie par le système de la main.

MRTK Pointer Line
CurvePointer

CurvePointer étend la classe LinePointer en autorisant des casts de rayons à plusieurs étapes le long d’une courbe. Cette classe de pointeur de base est utile pour les instances courbes telles que les pointeurs de téléportation où la ligne se plie de façon cohérente en parabole.

ShellHandRayPointer

L’implémentation de ShellHandRayPointer, qui s’étend de LinePointer, est utilisée comme valeur par défaut pour le profil de pointeur MRTK. Le prefab DefaultControllerPointer implémente la ShellHandRayPointer classe.

GGVPointer

Également connu sous le nom de pointeur De regard/Mouvement/Voix (GGV), le GGVPointer alimente HoloLens interactions de style 1 et appuyez principalement sur les interactions entre gaze et air tap ou gaz et voix Select. La position et la direction du pointeur GGV sont pilotées par la position et la rotation de la tête.

TouchPointer

TouchPointer est responsable de l’utilisation de l’entrée Tactile Unity (par exemple, l’écran tactile). Ce sont des « interactions éloignées », car l’acte de toucher l’écran projette un rayon de la caméra vers un emplacement potentiellement éloigné dans la scène.

MousePointer

MousePointer alimente un écran en raycast universel pour les interactions lointaines, mais pour la souris au lieu de la touche tactile.

Mouse pointer

Notes

La prise en charge de la souris n’est pas disponible par défaut dans MRTK, mais peut être activée en ajoutant une nouvelle Fournisseur de données de type MouseDeviceManager au profil d’entrée MRTK et en affectant le MixedRealityMouseInputProfile fournisseur de données.

Pointeurs proches

PokePointer

Le PokePointer est utilisé pour interagir avec les objets de jeu qui prennent en charge « interaction proche tactile ». qui sont gameObjects qui ont un script attaché NearInteractionTouchable . Dans le cas d’UnityUI, ce pointeur recherche nearInteractionTouchableUnityUIs. PokePointer utilise un SphereCast pour déterminer l’élément tactile le plus proche et est utilisé pour alimenter des éléments tels que les boutons pressables.

Lors de la configuration du GameObject avec le NearInteractionTouchable composant, veillez à configurer le paramètre localForward pour pointer vers l’avant du bouton ou un autre objet qui doit être tactile. Assurez-vous également que les limites de l’élément tactile correspondent aux limites de l’objet tactile.

Propriétés utiles du pointeur Poke :

  • TouchableDistance : distance maximale dans laquelle une surface tactile peut être interagissante
  • Visuels : objet de jeu utilisé pour restituer le visuel d’extrémité du doigt (l’anneau sur le doigt, par défaut).
  • Ligne : ligne facultative à dessiner du bout des doigts à la surface d’entrée active.
  • Masques de couche Poke - Tableau hiérarchisé de LayerMasks pour déterminer les objets GameObject possibles avec lesquels le pointeur peut interagir et l’ordre d’interaction à tenter. Notez qu’un GameObject doit également avoir un NearInteractionTouchable composant pour interagir avec un pointeur poke.
Poke Pointer
SpherePointer

SpherePointer utilise UnityEngine.Physics.OverlapSphere afin d’identifier l’objet le plus NearInteractionGrabbable proche pour l’interaction, ce qui est utile pour l’entrée « attrapable » comme le ManipulationHandler. À l’instar de la PokePointer/NearInteractionTouchable paire fonctionnelle, afin d’être interagissant avec le pointeur Sphere, l’objet de jeu doit contenir un composant qui est le NearInteractionGrabbable script.

Grab Pointer

Propriétés du pointeur Sphere utiles :

  • Rayon de cast de sphère : rayon de la sphère utilisée pour interroger des objets pouvant être saisis.
  • Marge d’objet proche : distance au-dessus du rayon de cast sphere pour rechercher si un objet est proche du pointeur. Total Near Object detection radius is Sphere Cast Radius + Near Object Margin
  • Angle de secteur d’objet proche : angle autour de l’axe avant du pointeur pour l’interrogation d’objets proches. Rend la fonction de IsNearObject requête comme un cône. Cette valeur est définie sur 66 degrés par défaut pour correspondre au comportement hololens 2

Sphere pointer modified to only query for objects in the forward direction

  • Facteur de lissage d’objet proche : facteur de lissage pour la détection d’objets proches. Si un objet est détecté dans le rayon de l’objet proche, le rayon interrogé devient rayon d’objet proche * (1 + Facteur de lissage d’objet proche) pour réduire la sensibilité et rendre plus difficile pour un objet de quitter la plage de détection.
  • Saisir des masques de couche : tableau hiérarchisé de LayerMasks pour déterminer les gameObjects possibles avec lesquels le pointeur peut interagir et l’ordre d’interaction à tenter. Notez qu’un GameObject doit également avoir une NearInteractionGrabbable interaction avec un SpherePointer.

    Notes

    La couche Reconnaissance spatiale est désactivée dans le préfabriqué GrabPointer par défaut fourni par MRTK. Cela permet de réduire l’impact sur les performances de l’exécution d’une requête de chevauchement de sphère avec le maillage spatial. Vous pouvez l’activer en modifiant le préfabriqué GrabPointer.

  • Ignore Colliders Not in FOV - Indique s’il faut ignorer les colliders qui peuvent être proches du pointeur, mais pas réellement dans le FOV visuel. Cela peut empêcher les saisies accidentelles, et permettra aux rayons de la main de s’activer quand vous pourriez être près d’un attrapable, mais ne peut pas le voir. Le FOV visuel est défini par le biais d’un cône au lieu du frustum typique pour des raisons de performances. Ce cône est centré et orienté de la même façon que le frustum de la caméra avec un rayon égal à la demi-hauteur d’affichage (ou FOV vertical).
Sphere Pointer

Pointeurs de téléport

  • TeleportPointer déclenche une demande de téléport lorsque l’action est effectuée (c’est-à-dire que le bouton de téléport est enfoncé) pour déplacer l’utilisateur.
  • ParabolicTeleportPointer déclenche une demande de téléport lorsque l’action est effectuée (c’est-à-dire que le bouton de téléport est enfoncé) avec un raycast de ligne parabolique afin de déplacer l’utilisateur.
Pointer Parabolic

Prise en charge du pointeur pour les plateformes de réalité mixte

Le tableau suivant détaille les types de pointeurs généralement utilisés pour les plateformes courantes dans MRTK. REMARQUE : il est possible d’ajouter différents types de pointeurs à ces plateformes. Par exemple, vous pouvez ajouter un pointeur Poke ou un pointeur Sphere à VR. En outre, les appareils VR avec un boîtier de commande peuvent utiliser le pointeur GGV.

Pointeur OpenVR Windows Mixed Reality HoloLens 1 HoloLens 2
ShellHandRayPointer Valide Valide Valide
TeleportPointer Valide Valide
GGVPointer Valide
SpherePointer Valide
PokePointer Valide

Interactions de pointeur via du code

Interfaces d’événement pointeur

MonoBehaviours qui implémentent une ou plusieurs des interfaces suivantes et qui sont affectés à un GameObject avec un Collider objet reçoit des événements d’interactions de pointeur comme défini par l’interface associée.

Événement Description Handler
Avant que le focus ne change / le focus a changé Déclenché sur l’objet de jeu qui perd le focus et celui qui l’obtient chaque fois qu’un pointeur change de focus. IMixedRealityFocusChangedHandler
Entrée/sortie du focus Déclenché sur l’objet de jeu qui prend le focus lorsque le premier pointeur l’entre et sur celui qui perd le focus lorsque le dernier pointeur le laisse. IMixedRealityFocusHandler
Pointeur vers le bas / glisser / Haut / Cliquer Déclenché pour appuyer sur le pointeur de rapport, faire glisser et libérer. IMixedRealityPointerHandler
Prise en main / Mise à jour / Terminé Déclenché par des pointeurs tactiles comme PokePointer pour signaler l’activité tactile. IMixedRealityTouchHandler

Notes

IMixedRealityFocusChangedHandler et IMixedRealityFocusHandler doit être géré dans les objets qu’ils sont déclenchés. Il est possible de recevoir des événements de focus globalement, mais, contrairement à d’autres événements d’entrée, le gestionnaire d’événements globaux ne bloque pas la réception d’événements en fonction du focus (l’événement sera reçu par le gestionnaire global et un objet correspondant au focus).

Événements d’entrée de pointeur en action

Les événements d’entrée de pointeur sont reconnus et gérés par le système d’entrée MRTK de la même façon que les événements d’entrée réguliers. La différence étant que les événements d’entrée de pointeur sont gérés uniquement par gameObject au focus par le pointeur qui a déclenché l’événement d’entrée, ainsi que tous les gestionnaires d’entrée globaux. Les événements d’entrée réguliers sont gérés par GameObjects au focus pour tous les pointeurs actifs.

  1. Le système d’entrée MRTK reconnaît qu’un événement d’entrée s’est produit
  2. Le système d’entrée MRTK déclenche la fonction d’interface appropriée pour l’événement d’entrée sur tous les gestionnaires d’entrée globaux inscrits
  3. Le système d’entrée détermine quel GameObject est en focus pour le pointeur qui a déclenché l’événement
    1. Le système d’entrée utilise le système d’événements Unity pour déclencher la fonction d’interface appropriée pour tous les composants correspondants sur gameObject ciblé
    2. Si à un moment donné, un événement d’entrée a été marqué comme utilisé, le processus se termine et aucun autre GameObjects ne reçoit de rappels.
      • Exemple : Les composants implémentant l’interface IMixedRealityFocusHandler seront recherchés pour obtenir un gain GameObject ou perdre le focus
      • Remarque : Le système d’événements Unity bulle jusqu’à rechercher le gameObject parent si aucun composant correspondant à l’interface souhaitée est trouvé sur l’objet GameObject actuel.
  4. Si aucun gestionnaire d’entrée global n’est inscrit et qu’aucun GameObject n’est trouvé avec un composant/interface correspondant, le système d’entrée appelle chaque gestionnaire d’entrée inscrit de secours

Exemple

Voici un exemple de script qui modifie la couleur du renderer attaché lorsqu’un pointeur prend ou quitte le focus ou lorsqu’un pointeur sélectionne l’objet.

public class ColorTap : MonoBehaviour, IMixedRealityFocusHandler, IMixedRealityPointerHandler
{
    private Color color_IdleState = Color.cyan;
    private Color color_OnHover = Color.white;
    private Color color_OnSelect = Color.blue;
    private Material material;

    private void Awake()
    {
        material = GetComponent<Renderer>().material;
    }

    void IMixedRealityFocusHandler.OnFocusEnter(FocusEventData eventData)
    {
        material.color = color_OnHover;
    }

    void IMixedRealityFocusHandler.OnFocusExit(FocusEventData eventData)
    {
        material.color = color_IdleState;
    }

    void IMixedRealityPointerHandler.OnPointerDown(
         MixedRealityPointerEventData eventData) { }

    void IMixedRealityPointerHandler.OnPointerDragged(
         MixedRealityPointerEventData eventData) { }

    void IMixedRealityPointerHandler.OnPointerClicked(MixedRealityPointerEventData eventData)
    {
        material.color = color_OnSelect;
    }
}

Pointeurs de requête

Il est possible de rassembler tous les pointeurs actuellement actifs en boucle dans les sources d’entrée disponibles (c’est-à-dire les contrôleurs et les entrées disponibles) pour découvrir quels pointeurs sont attachés.

var pointers = new HashSet<IMixedRealityPointer>();

// Find all valid pointers
foreach (var inputSource in CoreServices.InputSystem.DetectedInputSources)
{
    foreach (var pointer in inputSource.Pointers)
    {
        if (pointer.IsInteractionEnabled && !pointers.Contains(pointer))
        {
            pointers.Add(pointer);
        }
    }
}

Pointeur principal

Les développeurs peuvent s’abonner à l’événement FocusProviders PrimaryPointerChanged pour être avertis lorsque le pointeur principal du focus a changé. Cela peut être extrêmement utile pour identifier si l’utilisateur interagit actuellement avec une scène via un regard ou un rayon de main ou une autre source d’entrée.

private void OnEnable()
{
    var focusProvider = CoreServices.InputSystem?.FocusProvider;
    focusProvider?.SubscribeToPrimaryPointerChanged(OnPrimaryPointerChanged, true);
}

private void OnPrimaryPointerChanged(IMixedRealityPointer oldPointer, IMixedRealityPointer newPointer)
{
    ...
}

private void OnDisable()
{
    var focusProvider = CoreServices.InputSystem?.FocusProvider;
    focusProvider?.UnsubscribeFromPrimaryPointerChanged(OnPrimaryPointerChanged);

    // This flushes out the current primary pointer
    OnPrimaryPointerChanged(null, null);
}

La PrimaryPointerExample scène (Assets/MRTK/Examples/Demos/Input/Scenes/PrimaryPointer) montre comment utiliser les PrimaryPointerChangedHandler événements pour répondre à un nouveau pointeur principal.

Primary Pointer Example

Résultat du pointeur

La propriété pointeur Result contient le résultat actuel de la requête de scène utilisée pour déterminer l’objet avec focus. Pour un pointeur de raycast, comme ceux créés par défaut pour les contrôleurs de mouvement, l’entrée de regard et les rayons de main, il contiendra l’emplacement et la normale de l’impact de raycast.

private void IMixedRealityPointerHandler.OnPointerClicked(MixedRealityPointerEventData eventData)
{
    var result = eventData.Pointer.Result;
    var spawnPosition = result.Details.Point;
    var spawnRotation = Quaternion.LookRotation(result.Details.Normal);
    Instantiate(MyPrefab, spawnPosition, spawnRotation);
}

La PointerResultExample scène (Assets/MRTK/Examples/Demos/Input/Scene/PointerResult/PointerResultExample.unity) montre comment utiliser le pointeur Result pour générer un objet à l’emplacement d’accès.

Pointer Result

Désactiver les pointeurs

Pour activer et désactiver les pointeurs (par exemple, pour désactiver le rayon de main), définissez le PointerBehavior type de pointeur donné via PointerUtils.

// Disable the hand rays
PointerUtils.SetHandRayPointerBehavior(PointerBehavior.AlwaysOff);

// Disable hand rays for the right hand only
PointerUtils.SetHandRayPointerBehavior(PointerBehavior.AlwaysOff, Handedness.Right);

// Disable the gaze pointer
PointerUtils.SetGazePointerBehavior(PointerBehavior.AlwaysOff);

// Set the behavior to match HoloLens 1
// Note, if on HoloLens 2, you must configure your pointer profile to make the GGV pointer show up for articulated hands.
public void SetHoloLens1()
{
    PointerUtils.SetPokePointerBehavior(PointerBehavior.AlwaysOff, Handedness.Any);
    PointerUtils.SetGrabPointerBehavior(PointerBehavior.AlwaysOff, Handedness.Any);
    PointerUtils.SetRayPointerBehavior(PointerBehavior.AlwaysOff, Handedness.Any);
    PointerUtils.SetGGVBehavior(PointerBehavior.Default);
}

Consultez PointerUtils et TurnPointersOnOff pour obtenir d’autres exemples.

Interactions de pointeur via l’éditeur

Pour les événements de pointeur gérés par IMixedRealityPointerHandler, MRTK offre davantage de commodité sous la forme du PointerHandler composant, ce qui permet aux événements de pointeur d’être gérés directement via Les événements Unity.

Pointer Handler

Étendue du pointeur

Les pointeurs de loin ont des paramètres qui limitent la distance à laquelle ils vont raycast et interagir avec d’autres objets de la scène. Par défaut, cette valeur est définie sur 10 mètres. Cette valeur a été choisie pour rester cohérente avec le comportement de l’interpréteur de commandes HoloLens.

Cela peut être modifié en mettant à jour les DefaultControllerPointer champs du ShellHandRayPointer composant préfab :

Extension du pointeur : contrôle la distance maximale avec laquelle les pointeurs interagissent.

Extension du pointeur par défaut : contrôle la longueur du rayon/ligne de pointeur qui s’affiche lorsque le pointeur n’interagit pas avec n’importe quoi.

Voir aussi