Pointeurs — MRTK2

Pointeur

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

Les pointeurs sont automatiquement instances 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 dans l’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écider lequel est actif.

  • Étendue de pointage : 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 GameObjects 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 d’interface utilisateur avant d’autres objets de scène. Exemple de profil de pointeur

Configuration des options de pointeur

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

Exemple de profil d’options de pointeur

Chaque entrée de 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, le PokePointer est chargé de « piquer » les objets avec un doigt et est, par défaut, marqué comme prenant uniquement en charge le type de contrôleur de main articulé. Les pointeurs ne sont instanciés que lorsqu’un contrôleur devient disponible et en particulier le type de contrôleur définit les contrôleurs avec ́s ́s avec ́ ce préfabriqué de pointeur.
  • Handness : 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 la désactive efficacement du système comme alternative à la suppression de ce pointeur de la liste.

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

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

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 de manière programmatique, modifiez la BaseCursor propriété sur le comportement correspondant IMixedRealityPointer .

Cursor Prefab, propriété

Consultez nos préfabriqués de curseur dans Assets/MRTK/SDK/Features/UX/Prefabs/Cursors pour obtenir des exemples d’implémentations du comportement du curseur. En particulier, DefaultGazeCursor fournit 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 de pointeur attachés.

Pointeurs par défaut MRTK

Pointeurs lointains

LinePointer

LinePointer, une classe de pointeur de base, dessine une ligne de la source de l’entrée (c’est-à-dire le contrôleur) dans le sens du pointeur et prend en charge une seule projection de rayons dans cette direction. En règle générale, les classes enfants telles que et ShellHandRayPointer les pointeurs de téléportation sont instanciées et utilisées (qui dessinent également des lignes pour indiquer où la téléportation se termine) à la place de cette classe qui fournit principalement des fonctionnalités courantes.

Pour les contrôleurs de mouvement comme dans Oculus, 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 de pointage fournie par le système de la main.

LIGNE DE POINTEUR MRTK
CurvePointer

CurvePointer étend la classe LinePointer en autorisant les 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 constamment en une 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 préfabriqué DefaultControllerPointer implémente la ShellHandRayPointer classe .

GGVPointer

Également connu sous le nom de pointeur Gaze/Gesture/Voice (GGV), le GGVPointer alimente les interactions d’apparence et d’appui de style HoloLens 1, principalement par le biais de l’interaction Gaze et Air Tap ou Regarde et sélection vocale. La position et la direction du pointeur GGV sont pilotées par la position et la rotation de la tête.

TouchPointer

Le TouchPointer est responsable de l’utilisation de l’entrée Unity Touch (c’est-à-dire de l’écran tactile). Il s’agit d’interactions lointaines, car le fait de toucher l’écran projette un rayon de la caméra vers un emplacement potentiellement éloigné de la scène.

MousePointer

Le MousePointer alimente un écran au monde raycast pour les interactions éloignées, mais pour la souris au lieu du toucher.

Pointeur de souris

Notes

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

Pointeurs proches

PokePointer

Le PokePointer est utilisé pour interagir avec des objets de jeu qui prennent en charge « l’interaction proche tactile ». qui sont des GameObjects qui ont un script attaché NearInteractionTouchable . Dans le cas d’UnityUI, ce pointeur recherche NearInteractionTouchableUnityUIs. Le 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 appuyables.

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

Propriétés utiles du pointeur Poke :

  • TouchableDistance : distance maximale avec laquelle une surface tactile peut être interagissable
  • Visuels : objet de jeu utilisé pour restituer le visuel de pointe du doigt (l’anneau sur le doigt, par défaut).
  • Ligne : ligne facultative à dessiner du bout du doigt vers la surface d’entrée active.
  • Poke Layer Masques : tableau hiérarchisé de LayerMasks pour déterminer les éventuels GameObjects 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.
Pointeur poke
SpherePointer

SpherePointer utilise UnityEngine.Physics.OverlapSphere afin d’identifier l’objet d’interaction le plus NearInteractionGrabbable proche, ce qui est utile pour les entrées « saisissables » comme .ManipulationHandler Comme pour la PokePointer/NearInteractionTouchable paire fonctionnelle, pour pouvoir interagir avec le pointeur de sphère, l’objet de jeu doit contenir un composant qui est le NearInteractionGrabbable script.

Pointeur de récupération

Propriétés utiles du pointeur de sphère :

  • Rayon de cast de sphère : rayon de la sphère utilisée pour interroger les objets pouvant être saisis.
  • Marge de l’objet proche : distance au-dessus du rayon de cast de la sphère à interroger pour détecter si un objet se trouve près du pointeur. Le rayon total de détection d’objet proche est rayon de cast de sphère + marge d’objet proche
  • Angle du secteur de l’objet proche : angle autour de l’axe avant du pointeur pour l’interrogation d’objets à proximité. Rend la IsNearObject requête comme un cône. Cette valeur est définie sur 66 degrés par défaut pour correspondre au comportement d’Hololens 2

Pointeur de sphère modifié pour interroger uniquement les objets dans le sens vers l’avant

  • Facteur de lissage d’objet proche : facteur de lissage pour la détection d’objet proche. Si un objet est détecté dans le rayon de l’objet proche, le rayon interrogé devient rayon de l’objet proche * (1 + facteur de lissage de l’objet proche) pour réduire la sensibilité et rendre plus difficile pour un objet de quitter la plage de détection.
  • Récupérer 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 un NearInteractionGrabbable pour interagir avec un SpherePointer.

    Notes

    La couche Spatial Awareness 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 d’une requête de chevauchement de sphère avec le maillage spatial. Vous pouvez l’activer en modifiant le préfabriqué GrabPointer.

  • Ignorer les collisionneurs pas dans FOV : indique s’il faut ignorer les collisionneurs qui peuvent se trouver près du pointeur, mais pas réellement dans le FOV visuel. Cela peut éviter les captures accidentelles, et permettra aux rayons de la main de s’allumer quand vous êtes peut-être près d’un attrapable, mais ne peut pas le voir. Le FOV visuel est défini via un cône au lieu du frustum classique pour des raisons de performances. Ce cône est centré et orienté de la même façon que le frustum de l’appareil photo avec un rayon égal à la moitié de la hauteur d’affichage (ou À la hauteur verticale).
Pointeur de sphère

Pointeurs de téléportation

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

Prise en charge des pointeurs pour les plateformes de réalité mixte

Le tableau suivant détaille les types de pointeurs qui sont 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 dotés d’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 le code

Interfaces d’événement de pointeur

Les monoBehaviours qui implémentent une ou plusieurs des interfaces suivantes et qui sont affectés à un GameObject avec un Collider recevront des événements d’interaction de pointeur tels que définis 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 le gagne chaque fois qu’un pointeur change de focus. IMixedRealityFocusChangedHandler
Focus Entrée/Sortie Déclenché sur l’objet de jeu qui obtient le focus lorsque le premier pointeur l’entre et sur celui qui perd le focus lorsque le dernier pointeur le quitte. IMixedRealityFocusHandler
Pointeur vers le bas / Déplacé / Haut / Cliqué Déclenché pour appuyer sur le pointeur de rapport, faire glisser et relâcher. IMixedRealityPointerHandler
Contact démarré / mis à jour / terminé Déclenché par des pointeurs tactiles comme PokePointer pour signaler l’activité tactile. IMixedRealityTouchHandler

Notes

IMixedRealityFocusChangedHandler et IMixedRealityFocusHandler doivent être gérés dans les objets sur lesquels ils sont déclenchés. Il est possible de recevoir des événements 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 basés sur le focus (l’événement sera reçu à la fois par le gestionnaire global et un objet correspondant dans le 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 manière que les événements d’entrée standard. La différence étant que les événements d’entrée de pointeur sont gérés uniquement par le GameObject en 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 dans le 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 le GameObject ciblé
    2. Si, à un moment donné, un événement d’entrée a été marqué comme étant utilisé, le processus se termine et aucun autre GameObjects ne reçoit de rappels.
      • Exemple : les composants qui implémentent l’interface IMixedRealityFocusHandler sont recherchés pour un GameObject qui gagne ou perd le focus
      • Remarque : Le système d’événements Unity va buller pour rechercher le GameObject parent si aucun composant correspondant à l’interface souhaitée n’est trouvé sur le 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

Vous trouverez ci-dessous un exemple de script qui modifie la couleur du convertisseur 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 effectuant une boucle dans les sources d’entrée disponibles (c’est-à-dire les contrôleurs et les entrées disponibles) pour découvrir quels pointeurs y 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 dans le focus a changé. Cela peut être extrêmement utile pour déterminer si l’utilisateur interagit actuellement avec une scène par le biais d’un regard, d’un rayon de main ou d’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 le pour que les PrimaryPointerChangedHandler événements répondent à un nouveau pointeur principal.

Exemple de pointeur principal

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 le focus. Pour un pointeur de raycast, comme ceux créés par défaut pour les contrôleurs de mouvement, l’entrée du regard et les rayons de la 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/Scenes/PointerResult/PointerResultExample.unity) montre comment utiliser le pointeur Result pour générer un objet à l’emplacement d’accès.

Résultat du pointeur

Désactiver les pointeurs

Pour activer et désactiver les pointeurs (par exemple, pour désactiver le rayon de main), définissez le PointerBehavior pour un 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 plus d’exemples.

Interactions de pointeur via l’éditeur

Pour les événements de pointeur gérés par IMixedRealityPointerHandler, MRTK offre une commodité supplémentaire sous la forme du PointerHandler composant, ce qui permet de gérer les événements de pointeur directement via les événements Unity.

Gestionnaire de pointeur

Étendue du pointeur

Les pointeurs de distance 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 composant du ShellHandRayPointer préfabriqué :

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

Étendue du pointeur par défaut : contrôle la longueur du rayon/de la ligne du pointeur qui s’affiche lorsque le pointeur n’interagit avec rien.

Voir aussi