Pointers

Aanwijzer

In dit artikel wordt uitgelegd hoe u pointer-invoer in de praktijk configureert en erop reageert, vergeleken met pointer-architectuur

Aanwijzers worden tijdens runtime automatisch uitgevoerd wanneer een nieuwe controller wordt gedetecteerd. Er kan meer dan één aanwijzer worden gekoppeld aan een controller. Met het standaard-aanwijzerprofiel krijgen Windows Mixed Reality controllers respectievelijk een lijn en een parabolische aanwijzer voor normale selectie en teleportatie.

Aanwijzerconfiguratie

Aanwijzers worden geconfigureerd als onderdeel van het invoersysteem in MRTK via een MixedRealityPointerProfile . Dit type profiel wordt toegewezen aan een MixedRealityInputSystemProfile in de inspector MRTK-configuratie. Het aanwijzerprofiel bepaalt de cursor, de typen aanwijzers die beschikbaar zijn tijdens runtime en hoe deze aanwijzers met elkaar communiceren om te bepalen welke actief is.

  • Aanwijzende omvang: hiermee definieert u de maximale afstand waarvoor een pointer met een GameObject kan communiceren.

  • Raycast-laagmaskers aanwijzen: dit is een geprioriteerde matrix van LayerMasks om te bepalen met welke mogelijke GameObjects een bepaalde pointer kan communiceren en de volgorde van de interactie die kan worden geprobeerd. Dit kan handig zijn om ervoor te zorgen dat pointers eerst met UI-elementen communiceren vóór andere scèneobjecten. Voorbeeld van aanwijzerprofiel

Configuratie van aanwijzeropties

De standaardconfiguratie van MRTK Pointer Profile bevat de volgende aanwijzerklassen en bijbehorende standaard prefabs. De lijst met aanwijzers die tijdens runtime beschikbaar zijn voor het systeem, wordt gedefinieerd onder Aanwijzeropties in het pointerprofiel. Ontwikkelaars kunnen deze lijst gebruiken om bestaande aanwijzers opnieuw te configureren, nieuwe aanwijzers toe te voegen of er een te verwijderen.

Voorbeeld van een aanwijzeroptiesprofiel

Elke pointer-vermelding wordt gedefinieerd door de volgende set gegevens:

  • Controllertype: de set controllers waar een aanwijzer geldig voor is.

    • De MoetePointer is bijvoorbeeld verantwoordelijk voor het 'afsteken' van objecten met een vinger en is standaard gemarkeerd als alleen ter ondersteuning van het type gearticeerde handcontroller. Aanwijzers worden alleen gemaakt wanneer een controller beschikbaar komt en met name het controllertype definieert met welke controllers deze aanwijzer prefab kan worden gemaakt.
  • Handigheid: hiermee staat u toe dat een aanwijzer alleen wordt gemaakt voor een specifieke hand (links/rechts)

Notitie

Als u de eigenschap Handigheid van een pointer-vermelding instelt op Geen, wordt deze effectief uitgeschakeld vanuit het systeem als alternatief voor het verwijderen van die aanwijzer uit de lijst.

  • Pointer Prefab: deze prefab-asset wordt gestart wanneer een controller die overeenkomt met het opgegeven controllertype en de handigheid wordt getypt.

Het is mogelijk om meerdere aanwijzers te hebben die zijn gekoppeld aan een controller. In DefaultHoloLens2InputSystemProfile (Assets/MRTK/SDK/Profiles/HoloLens2/) is de verwoorde handcontroller bijvoorbeeld gekoppeld aan de DefaultHoloLens2InputSystemProfileGrabPointeren de DefaultControllerPointer (dat wil zeggen handfoto's).

Notitie

MRTK biedt een set aanwijzerprefabs in Assets/MRTK/SDK/Features/UX/Prefabs/Pointers. Een nieuwe aangepaste prefab kan worden gebouwd zolang deze een van de aanwijzerscripts bevat in Assets/MRTK/SDK/Features/UX/Scripts/Pointers of een ander script dat implementeert.

Cursorconfiguratie

De cursor Staren kan rechtstreeks worden geconfigureerd via de GazeCursorPrefab eigenschap in MixedRealityInputSystemProfile de editor. Als u de cursor wilt configureren die wordt gebruikt voor andere aanwijzers, moet u prefab wijzigen dat wordt gebruikt in het CursorPrefab veld van de bijbehorende BaseControllerPointer . Als u de cursor programmatisch wilt wijzigen, wijzigt u BaseCursor de eigenschap in het bijbehorende IMixedRealityPointer gedrag.

Eigenschap Cursorprefab

Zie onze cursorprefabs in Assets/MRTK/SDK/Features/UX/Prefabs/Cursors voor bijvoorbeeld implementaties van cursorgedrag. De DefaultGazeCursor biedt met name een robuuste implementatie van het wijzigen van de afbeelding van de cursor op basis van contextuele status.

Standaard aanwijzerklassen

De volgende klassen zijn de out-of-box MRTK-aanwijzers die beschikbaar zijn en zijn gedefinieerd in het standaard MRTK-pointerprofiel dat hierboven wordt beschreven. Elke pointer-prefab onder Assets/MRTK/SDK/Features/UX/Prefabs/Pointers bevat een van de gekoppelde pointeronderdelen.

MRTK-standaard pointers

Veel aanwijzers

LinePointer

LinePointer,een klasse met een basispunt, tekent een lijn uit de bron van de invoer (dat wil zeggen de controller) in de richting van de aanwijzer en ondersteunt één raycast in deze richting. Over het algemeen worden kinderenklassen zoals de en detelteletelepunters gemaakt en gebruikt (die ook lijnen tekenen om aan te geven waar de teleportatie eindigt) in plaats van deze klasse, die voornamelijk algemene functionaliteit ShellHandRayPointer biedt.

Voor bewegingscontrollers zoals in Oculus, Vive en Windows Mixed Reality, komt de rotatie overeen met de rotatie van de controller. Voor andere controllers, zoals HoloLens 2, komt de rotatie overeen met de door het systeem opgegeven wijzende houding van de hand.

MRTK-aanwijzerlijn
CurvePointer

CurvePointer breidt de LinePointer-klasse uit door raycasts met meerdere stappen toe te staan langs een curve. Deze klasse met aanwijzers is handig voor gecurvede exemplaren, zoals teleportatiepuntjes, waarbij de lijn consistent in een parabola wordt omsloten.

ShellHandRayPointer

De implementatie van ShellHandRayPointer, die is uitgebreid van , wordt gebruikt als de standaardinstelling voor het MRTK-pointerprofiel. De defaultControllerPointer prefab implementeert de klasse.

GGVPointer

De GGVPointer, ook wel bekend als de aanwijzer Star/Gesture/Voice (GGV), maakt gebruik van HoloLens 1-stijl look en tapinteracties, voornamelijk via Staren en lucht tikken of Interactie tussen staren en spraak selecteren. De positie en richting van de GGV-aanwijzer worden aangestuurd door de positie en draaiing van de kop.

TouchPointer

TouchPointer is verantwoordelijk voor het werken met Unity Touch-invoer (bijvoorbeeld aanraakscherm). Dit zijn 'verre interacties', omdat door het aanraken van het scherm een straal van de camera naar een mogelijk verre locatie in de scène wordt gecast.

MousePointer

De MousePointer geeft een scherm aan de wereld raycast voor verre interacties, maar voor muis in plaats van aanraken.

Muisaanwijzer

Notitie

Muisondersteuning is niet standaard beschikbaar in MRTK, maar kan worden ingeschakeld door een nieuwe invoergegevensprovider van het type toe te voegen aan het MRTK-invoerprofiel en de toe te wijzen aan de MixedRealityMouseInputProfile gegevensprovider.

Aanwijzers in de buurt

PokePointer

De MoetePointer wordt gebruikt om te communiceren met gameobjecten die ondersteuning bieden voor 'near interaction touchable'. dit zijn GameObjects die een gekoppeld NearInteractionTouchable script hebben. In het geval van UnityUI zoekt deze aanwijzer naar NearInteractionTouchableUnityUIs. De MoetePointer gebruikt een SphereCast om het dichtstbijzijnde aanraakbare element te bepalen en wordt gebruikt om zaken zoals de knoppen in te drukken.

Bij het configureren van het GameObject met het onderdeel moet u de parameter localForward zo configureren dat deze naar de voorkant van de knop of een ander object wijzen dat NearInteractionTouchable aanraakbaar moet worden gemaakt. NearInteractionTouchable Zorg er ook voor dat de grenzen van het aanraakbare object overeenkomt met de grenzen van het aanraakbare object.

Handige eigenschappen van de Pointer voor Handig:

  • TouchableDistance:Maximale afstand waarmee een aanraakbaar oppervlak kan worden gebruikt
  • Visuals:gameobject dat wordt gebruikt voor het renderen van het visuele vingerpunt (de ring op de vinger, standaard).
  • Regel:optionele lijn om vanaf de hand van de hand naar het actieve invoeroppervlak te tekenen.
  • Layer Masks: een geprioriteerde matrix van LayerMasks om te bepalen met welke mogelijke GameObjecten de aanwijzer kan communiceren en de volgorde van de interactie die moet worden geprobeerd. Houd er rekening mee dat een GameObject ook een onderdeel moet hebben om te NearInteractionTouchable kunnen communiceren met een pointer.
De pointer voor Het aanwijzeren van de wijzer
SpherePointer

De SpherePointer maakt gebruik van UnityEngine.Physics.OverlapSphere om het dichtstbijzijnde object voor interactie te identificeren, wat handig is voor 'grabbable' invoer zoals de . Net als bij het functionele paar moet het gameobject een onderdeel bevatten dat het script is om te kunnen communiceren met de PokePointer/NearInteractionTouchable Sphere-aanwijzer. NearInteractionGrabbable

Grab Pointer

Nuttige sphere-aanwijzereigenschappen:

  • Sphere Cast Radius:de radius voor de bol die wordt gebruikt om te zoeken naar pakkende objecten.
  • Near Object Margin:de afstand boven op de Sphere Cast Radius om te zoeken naar het detecteren of een object zich in de buurt van de aanwijzer bevinden. De totale radius voor de detectie van objecten in de buurt is Sphere Cast Radius + Near Object Margin
  • Near Object Sector Angle:de hoek rond de vooras van de aanwijzer voor het uitvoeren van query's op objecten in de buurt. Maakt de IsNearObject queryfunctie als een ijsje. Deze is standaard ingesteld op 66 graden om te overeenkomen met het hololens 2-gedrag

Sphere-aanwijzer gewijzigd om alleen objecten in de voorwaartse richting op te vragen

  • Near Object Smoothing Factor:Smoothing factor for Near Object Detection. Als een object wordt gedetecteerd in de Near Object Radius, wordt de opgevraagde radius vervolgens Near Object Radius * (1 + Near Object Smoothing Factor) om de gevoeligheid te verminderen en het moeilijker te maken voor een object om het detectiebereik te verlaten.
  • Laagmaskers pakken: een geprioriteerde matrix van LayerMasks om te bepalen met welke mogelijke GameObjecten de aanwijzer kan communiceren en de volgorde van de interactie die moet worden geprobeerd. Houd er rekening mee dat een GameObject ook een NearInteractionGrabbable moet hebben om te communiceren met een SpherePointer.

    Notitie

    De laag Spatial Awareness is uitgeschakeld in de standaardPrefab van GrabPointer van MRTK. Dit wordt gedaan om de invloed op de prestaties te verminderen van het uitvoeren van een sphere-overlapquery met de ruimtelijke mesh. U kunt dit inschakelen door het prefab van GrabPointer te wijzigen.

  • Colliders negeren niet in FOV: geeft aan of colliders moeten worden genegeerd die zich in de buurt van de aanwijzer kunnen hebben, maar niet daadwerkelijk in de visuele FOV. Dit kan onbedoelde grepen voorkomen en zorgt ervoor dat handfoto's kunnen worden in- of uitgelopen wanneer u in de buurt bent van een pak, maar deze niet kunt zien. De Visual FOV wordt om prestatieredenen gedefinieerd via een ijsje in plaats van het typische frustum. Dit ijsje is gecentreerd en is hetzelfde als het frustum van de camera met een radius die gelijk is aan de helft van de weergavehoogte (of verticale FOV).
Bol-aanwijzer

Teleporters

  • TeleportPointer zal eenteleportaanvraag doen wanneer er actie wordt ondernomen (dat wil zeggen dat er op detelknop wordt gedrukt) om de gebruiker te verplaatsen.
  • ParabolicTeleportPointer zal eenteleportaanvraag doen wanneer er een actie wordt ondernomen (dat wil zeggen dat detelportatieknop wordt ingedrukt) met een raycast met een parabolische lijn om de gebruiker te verplaatsen.
Aanwijzerparabolisch

Pointer-ondersteuning voor mixed reality platforms

In de volgende tabel staan de aanwijzertypen die doorgaans worden gebruikt voor de algemene platforms in MRTK. OPMERKING: het is mogelijk om verschillende aanwijzertypen toe te voegen aan deze platformen. U kunt bijvoorbeeld een Pointer of Sphere-aanwijzer toevoegen aan VR. Daarnaast kunnen VR-apparaten met een gamepad gebruikmaken van de GGV-aanwijzer.

Aanwijzer OpenVR Windows Mixed Reality HoloLens 1 HoloLens 2
ShellHandRayPointer Geldig Geldig Geldig
Teleportpointer Geldig Geldig
GGVPointer Geldig
SpherePointer Geldig
HadoPointer Geldig

Pointer-interacties via code

Pointer-gebeurtenisinterfaces

MonoBehaviours die een of meer van de volgende interfaces implementeren en zijn toegewezen aan een GameObject met een ontvangt pointer interactiegebeurtenissen zoals gedefinieerd door de Collider gekoppelde interface.

Gebeurtenis Beschrijving Handler
Voordat de focus werd gewijzigd/focus werd gewijzigd Zowel het gameobject dat de focus verliest als het object dat de focus verliest telkens als een aanwijzer de focus wijzigt. IMixedRealityFocusChangedHandler
Focus invoeren/afsluiten De focus op het gameobject wordt verhoogd wanneer de eerste aanwijzer het object binnenkomt en op het object dat de focus verliest wanneer de laatste aanwijzer het object verlaat. IMixedRealityFocusHandler
Aanwijzer omlaag / gesleept / omhoog / erop geklikt Verhoogd tot rapportwijzer door op te drukken, slepen en vrijgeven. IMixedRealityPointerHandler
Aanraking gestart/bijgewerkt/voltooid Veroorzaakt door aanraakbewuste aanwijzers, zoals PokePointer om aanraakactiviteit te rapporteren. IMixedRealityTouchHandler

Notitie

IMixedRealityFocusChangedHandler en IMixedRealityFocusHandler moeten worden verwerkt in de objecten waarin ze worden verhoogd. Het is mogelijk om focusgebeurtenissen wereldwijd te ontvangen, maar in tegenstelling tot andere invoergebeurtenissen blokkeert de globale gebeurtenis-handler niet het ontvangen van gebeurtenissen op basis van focus (de gebeurtenis wordt ontvangen door zowel de globale handler als een bijbehorend object in focus).

Invoergebeurtenissen van aanwijzer in actie

Invoergebeurtenissen van aanwijzers worden herkend en verwerkt door het MRTK-invoersysteem op een vergelijkbare manier als gewone invoergebeurtenissen. Het verschil is dat invoergebeurtenissen van aanwijzers alleen worden verwerkt door het GameObject in focus door de aanwijzer die de invoergebeurtenis heeft uitgevoerd, evenals globale invoer-handlers. Reguliere invoergebeurtenissen worden verwerkt door GameObjects in focus voor alle actieve aanwijzers.

  1. Het MRTK-invoersysteem herkent dat er een invoergebeurtenis is opgetreden
  2. Het MRTK-invoersysteem geeft de relevante interfacefunctie voor de invoergebeurtenis aan alle geregistreerde globale invoer-handlers
  3. Het invoersysteem bepaalt welk GameObject zich richt op de aanwijzer die de gebeurtenis heeft afgelost
    1. Het invoersysteem maakt gebruik van het Gebeurtenissysteem van Unity om de relevante interfacefunctie voor alle overeenkomende onderdelen op het betreffende GameObject te firen
    2. Als een invoergebeurtenis op enig moment is gemarkeerd als gebruikt,wordt het proces beëindigen en worden er geen verdere GameObjects meer callbacks ontvangen.
      • Voorbeeld: Onderdelen die de interface implementeren, IMixedRealityFocusHandler worden gezocht naar een GameObject of de focus wordt verloren
      • Opmerking: Het Unity Event System gaat bellen om te zoeken naar het bovenliggende GameObject als er geen onderdelen zijn gevonden die overeenkomen met de gewenste interface op het huidige GameObject..
  4. Als er geen globale invoer-handlers zijn geregistreerd en er geen GameObject wordt gevonden met een overeenkomende component/interface, roept het invoersysteem elke geregistreerde terugvalinvoer-handlers aan

Voorbeeld

Hieronder vindt u een voorbeeldscript dat de kleur van de gekoppelde renderer wijzigt wanneer een aanwijzer de focus neemt of verlaat of wanneer een aanwijzer het object selecteert.

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

Query-aanwijzers

Het is mogelijk om alle aanwijzers te verzamelen die momenteel actief zijn door de beschikbare invoerbronnen (dat wil zeggen beschikbare controllers en invoerbronnen) te herhalen om te ontdekken welke aanwijzers eraan zijn gekoppeld.

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

Primaire aanwijzer

Ontwikkelaars kunnen zich abonneren op de gebeurtenis FocusProviders PrimaryPointerChanged om een melding te ontvangen wanneer de primaire aanwijzer in focus is gewijzigd. Dit kan zeer nuttig zijn om te bepalen of de gebruiker momenteel met een scène communiceert via staren, een hand ray of een andere invoerbron.

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

De PrimaryPointerExample scène (Assets/MRTK/Examples/Demos/Input/Scenes/PrimaryPointer) laat zien hoe de voor gebeurtenissen moet worden gebruikt om te reageren op een nieuwe PrimaryPointerChangedHandler primaire aanwijzer.

Voorbeeld van primaire aanwijzer

Resultaat van aanwijzer

De Result aanwijzer-eigenschap bevat het huidige resultaat voor de scènequery die wordt gebruikt om het object met focus te bepalen. Voor een raycast-pointer, zoals degene die standaard zijn gemaakt voor bewegingscontrollers, staren invoer en handfoto's, bevat deze de locatie en de normale van de raycast-treffer.

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

De PointerResultExample scène (Assets/MRTK/Examples/Demos/Input/Scenes/PointerResult/PointerResultExample.unity) laat zien hoe u de aanwijzer gebruikt om een object op de trefferlocatie te Result maken.

Resultaat van aanwijzer

Aanwijzers uitschakelen

Als u aanwijzers wilt in- en uitschakelen (bijvoorbeeld om de hand ray uit te schakelen), stelt u de in voor een PointerBehavior bepaald type aanwijzer 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);
}

Zie PointerUtils en voor meer TurnPointersOnOff voorbeelden.

Pointer-interacties via de editor

Voor aanwijzergebeurtenissen die door worden verwerkt, biedt MRTK meer gemak in de vorm van het onderdeel, waardoor aanwijzergebeurtenissen rechtstreeks IMixedRealityPointerHandler via Unity-gebeurtenissen kunnen worden PointerHandler verwerkt.

Aanwijzer-handler

Pointer-omvang

Veel aanwijzers hebben instellingen die de afstand tot raycast beperken en interactie hebben met andere objecten in de scène. Deze waarde is standaard ingesteld op 10 meter. Deze waarde is gekozen om consistent te blijven met het gedrag van de HoloLens shell.

Dit kan worden gewijzigd door de velden van het DefaultControllerPointer onderdeel prefab ShellHandRayPointer bij te werken:

Pointer Extent: hiermee bepaalt u de maximale afstand die aanwijzers gebruiken.

Standaard pointer extent: hiermee bepaalt u de lengte van de ray/line van de aanwijzer die wordt weergegeven wanneer de aanwijzer niets gebruikt.

Zie ook