Pointeurs — MRTK2
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.
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.
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
.
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 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.
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.
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.
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.
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
- 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).
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.
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.
- Le système d’entrée MRTK reconnaît qu’un événement d’entrée s’est produit
- 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
- Le système d’entrée détermine quel GameObject est en focus pour le pointeur qui a déclenché l’événement
- 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é
- 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.
- Exemple : les composants qui implémentent l’interface
- 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.
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.
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.
É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.