Puntatori - MRTK2

Pointer

Questo articolo illustra come configurare e rispondere all'input del puntatore nella pratica. Per comprendere meglio come controllare più puntatori a un livello generale, vedere Architettura del puntatore.

I puntatori vengono istanze automaticamente in fase di esecuzione quando viene rilevato un nuovo controller. È possibile collegare più puntatori a un controller. Ad esempio, con il profilo del puntatore predefinito, Windows Mixed Reality controller ottengono rispettivamente una linea e un puntatore parabolico per la selezione normale e il teleportamento.

Configurazione del puntatore

I puntatori vengono configurati come parte del sistema di input in MRTK tramite .MixedRealityPointerProfile Questo tipo di profilo viene assegnato a un MixedRealityInputSystemProfile nel controllo configurazione MRTK. Il profilo puntatore determina il cursore, i tipi di puntatori disponibili in fase di esecuzione e il modo in cui questi puntatori comunicano tra loro per decidere quale puntatore è attivo.

  • Extent di puntamento : definisce la distanza massima per cui un puntatore può interagire con un GameObject.

  • Pointing Raycast Layer Masks ( Maschera di livello Raycast- Si tratta di una matrice con priorità di LayerMasks) per determinare i possibili GameObject con cui qualsiasi puntatore specificato può interagire e l'ordine di interazione da tentare. Questo può essere utile per garantire che i puntatori interagiscono con gli elementi dell'interfaccia utente prima di altri oggetti della scena. Pointer Profile Example

Configurazione delle opzioni del puntatore

La configurazione predefinita del profilo puntatore MRTK include le classi puntatore seguenti e i prefab associati predefiniti. L'elenco dei puntatori disponibili per il sistema in fase di esecuzione è definito in Opzioni puntatore nel profilo puntatore. Gli sviluppatori possono usare questo elenco per riconfigurare i puntatori esistenti, aggiungere nuovi puntatori o eliminarli.

Pointer Options Profile Example

Ogni voce puntatore è definita dal set di dati seguente:

  • Tipo di controller : set di controller per cui un puntatore è valido.

    • Ad esempio, PokePointer è responsabile di oggetti "poking" con un dito ed è, per impostazione predefinita, contrassegnata come solo per supportare il tipo di controller di mano articolato. I puntatori vengono creati solo quando un controller diventa disponibile e in particolare il tipo di controller definisce i controller con cui è possibile creare il prefab del puntatore.
  • Mani: consente a un puntatore di creare un'istanza solo per una mano specifica (sinistra/destra)

Nota

L'impostazione della proprietà Handedness di una voce puntatore su Nessuno lo disabiliterà effettivamente dal sistema come alternativa alla rimozione di tale puntatore dall'elenco.

  • Prefab puntatore : questo asset di prefab verrà creata un'istanza quando un controller corrispondente al tipo di controller e alla mano specificati inizia a essere monitorato.

È possibile associare più puntatori a un controller. Ad esempio, in DefaultHoloLens2InputSystemProfile (Assets/MRTK/SDK/Profiles/HoloLens2/) il controller mano articolato è associato a PokePointer, GrabPointer e DefaultControllerPointer (ad esempio i raggi della mano).

Nota

MRTK fornisce un set di prefab del puntatore in Assets/MRTK/SDK/Features/UX/Prefabs/Pointers. È possibile compilare un nuovo prefab personalizzato purché contenga uno degli script del puntatore in Assets/MRTK/SDK/Features/UX/Scripts/Pointers o qualsiasi altro script che implementa IMixedRealityPointer.

Configurazione del cursore

Il cursore Sguardo fisso è configurabile direttamente tramite la GazeCursorPrefab proprietà nell'editor MixedRealityInputSystemProfile . Per configurare il cursore usato per altri puntatori, è necessario modificare il CursorPrefab prefab usato nel campo dell'oggetto corrispondente BaseControllerPointer. Per modificare il cursore a livello di codice, modificare la BaseCursor proprietà sul comportamento corrispondente IMixedRealityPointer .

Cursor Prefab Property

Vedere i prefab del cursore in Assets/MRTK/SDK/Features/UX/Prefabs/Cursors , ad esempio implementazioni del comportamento del cursore. In particolare, DefaultGazeCursor offre un'implementazione affidabile della modifica dell'elemento grafico del cursore in base allo stato contestuale.

Classi puntatore predefinite

Le classi seguenti sono i puntatori MRTK predefiniti disponibili e definiti nel profilo di puntatore MRTK predefinito descritto in precedenza. Ogni prefab puntatore fornito in Assets/MRTK/SDK/Features/UX/Prefabs/Pointers contiene uno dei componenti del puntatore collegati.

MRTK Default Pointers

Puntatori lontani

LinePointer

LinePointer, una classe di puntatore di base, disegna una linea dall'origine dell'input (ad esempio il controller) nella direzione del puntatore e supporta un singolo cast di raggi in questa direzione. In genere, le classi figlio come ShellHandRayPointer e i puntatori di teletrasportazione vengono create e utilizzate (che disegnano anche linee per indicare dove finisce il teletrasporto) anziché questa classe che fornisce principalmente funzionalità comuni.

Per i controller del movimento come in Oculus, Vive e Windows Mixed Reality, la rotazione corrisponderà alla rotazione del controller. Per altri controller come HoloLens 2 mani articolate, la rotazione corrisponde alla posizione di puntamento fornita dal sistema della mano.

MRTK Pointer Line
CurvePointer

CurvePointer estende la classe LinePointer consentendo il cast di raggi in più passaggi lungo una curva. Questa classe di puntatore di base è utile per le istanze curve, ad esempio i puntatori di teleportazione in cui la linea si piega costantemente in una parabola.

ShellHandRayPointer

L'implementazione di ShellHandRayPointer, che si estende da LinePointer, viene usata come impostazione predefinita per il profilo puntatore MRTK. Il prefab DefaultControllerPointer implementa la ShellHandRayPointer classe .

GGVPointer

Noto anche come puntatore sguardo fisso/movimento/voce (GGV), il GGVPointer alimenta HoloLens interazioni di stile 1 e tocco, principalmente tramite tocco sguardo e aria o sguardo fisso e interazione di selezione vocale. La posizione e la direzione del puntatore GGV sono guidate dalla posizione e dalla rotazione della testa.

TouchPointer

TouchPointer è responsabile dell'uso dell'input Touch di Unity (ad esempio touchscreen). Queste sono "interazioni lontane" perché l'atto di toccare lo schermo eseguirà il cast di un raggio dalla fotocamera a una posizione potenzialmente lontana nella scena.

MousePointer

MousePointer alimenta uno schermo al raycast globale per le interazioni lontane, ma per il mouse invece del tocco.

Mouse pointer

Nota

Il supporto del mouse non è disponibile per impostazione predefinita in MRTK, ma può essere abilitato aggiungendo un nuovo input provider di dati di tipo MouseDeviceManager al profilo di input MRTK e assegnando al MixedRealityMouseInputProfile provider di dati.

Puntatori vicini

PokePointer

Il PokePointer viene usato per interagire con gli oggetti del gioco che supportano "near interaction touchable". che sono GameObject che hanno uno script associato NearInteractionTouchable . Nel caso di UnityUI, questo puntatore cerca NearInteractionTouchableUnityUIs. PokePointer usa sphereCast per determinare l'elemento toccabile più vicino e viene usato per alimentare elementi come i pulsanti premuti.

Quando si configura GameObject con il NearInteractionTouchable componente, assicurarsi di configurare il parametro localForward in modo che punti dalla parte anteriore del pulsante o da un altro oggetto che deve essere reso toccabile. Assicurarsi inoltre che i limiti del touchable corrispondano ai limiti dell'oggetto toccabile.

Proprietà utili del puntatore poke:

  • TouchableDistance: distanza massima con cui è possibile interagire una superficie toccabile
  • Oggetti visivi: oggetto gioco usato per eseguire il rendering dell'oggetto visivo punta del dito (l'anello sul dito, per impostazione predefinita).
  • Linea: linea facoltativa da disegnare dalla punta del dito alla superficie di input attiva.
  • Maschera livello poke : matrice con priorità di LayerMasks per determinare con quali possibili oggetti GameObject il puntatore può interagire e l'ordine di interazione da tentare. Si noti che un GameObject deve avere anche un NearInteractionTouchable componente per interagire con un puntatore a un poke.
Poke Pointer
SpherePointer

SpherePointer usa UnityEngine.Physics.OverlapSphere per identificare l'oggetto più NearInteractionGrabbable vicino per l'interazione, utile per l'input "afferrabile" come .ManipulationHandler Analogamente alla PokePointer/NearInteractionTouchable coppia funzionale, per poter interagire con il puntatore Sphere, l'oggetto gioco deve contenere un componente che è lo NearInteractionGrabbable script.

Grab Pointer

Proprietà utili del puntatore a sfera:

  • Raggio cast sfera: raggio della sfera usata per eseguire una query per gli oggetti afferrabili.
  • Margine oggetto vicino: la distanza sopra il raggio cast sphere per eseguire una query per rilevare se un oggetto si trova vicino al puntatore. Il raggio totale di rilevamento oggetti vicini è Raggio cast sfera + Margine oggetto vicino
  • Angolo del settore oggetti vicino: angolo attorno all'asse in avanti del puntatore per l'esecuzione di query per gli oggetti vicini. Rende la funzione di IsNearObject query come un cono. Questa opzione è impostata su 66 gradi per impostazione predefinita in modo che corrisponda al comportamento di Hololens 2

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

  • Near Object Smoothing Factor: fattore di smussamento per il rilevamento di oggetti vicini. Se viene rilevato un oggetto nel raggio dell'oggetto near, il raggio sottoposto a query diventa Near Object Radius * (1 + Near Object Smoothing Factor) per ridurre la sensibilità e rendere più difficile per un oggetto lasciare l'intervallo di rilevamento.
  • Grab Layer Masks : matrice con priorità di LayerMasks per determinare con quali possibili oggetti GameObject il puntatore può interagire e l'ordine di interazione da tentare. Si noti che un GameObject deve avere anche un oggetto NearInteractionGrabbable per interagire con un Oggetto SpherePointer.

    Nota

    Il livello Di consapevolezza spaziale è disabilitato nel prefab GrabPointer predefinito fornito da MRTK. Questa operazione viene eseguita per ridurre l'impatto sulle prestazioni dell'esecuzione di una query di sovrapposizione sphere con la mesh spaziale. È possibile abilitare questa operazione modificando il prefab GrabPointer.

  • Ignora colliders Non in FOV : indica se ignorare i collisori che potrebbero essere vicini al puntatore, ma non effettivamente nel FOV visivo. Ciò può impedire afferramenti accidentali e permetterà ai raggi della mano di accendersi quando si potrebbe essere vicino a un afferrabile ma non può vederlo. Visual FOV viene definito tramite un cono anziché il frustum tipico per motivi di prestazioni. Questo cono è centrato e orientato allo stesso modo del frustum della fotocamera con un raggio uguale a metà altezza dello schermo (o FOV verticale).
Sphere Pointer

Puntatori di teletrasporto

  • TeleportPointer genererà una richiesta di teletrasporto quando viene eseguita un'azione (ad esempio, il pulsante di teletrasporto viene premuto) per spostare l'utente.
  • ParabolicTeleportPointer genererà una richiesta di teletrasporto quando viene eseguita un'azione (ad esempio il pulsante di teletrasporto premuto) con un raycast di linea parabolico per spostare l'utente.
Pointer Parabolic

Supporto del puntatore per le piattaforme di realtà mista

Nella tabella seguente vengono descritti in dettaglio i tipi di puntatore usati in genere per le piattaforme comuni in MRTK. NOTA: è possibile aggiungere tipi di puntatore diversi a queste piattaforme. Ad esempio, è possibile aggiungere un puntatore Poke o un puntatore Sphere alla realtà virtuale. Inoltre, i dispositivi VR con un game pad potrebbero usare il puntatore GGV.

Puntatore OpenVR Windows Mixed Reality HoloLens 1 HoloLens 2
ShellHandRayPointer Valido Valido Valido
TeleportPointer Valido Valido
GGVPointer Valido
SpherePointer Valido
PokePointer Valido

Interazioni del puntatore tramite codice

Interfacce evento puntatore

MonoBehaviours che implementa una o più delle interfacce seguenti e vengono assegnati a un GameObject con un Collider oggetto riceverà gli eventi di interazione del puntatore come definito dall'interfaccia associata.

Event Descrizione Gestore
Prima della modifica dello stato attivo/modifica dello stato attivo Generato sia sull'oggetto gioco che perde lo stato attivo e quello che lo ottiene ogni volta che un puntatore cambia lo stato attivo. IMixedRealityFocusChangedHandler
Messa a fuoco Invio/Uscita Generato sull'oggetto gioco ottenendo lo stato attivo quando il primo puntatore entra e su quello perde lo stato attivo quando l'ultimo puntatore lo lascia. IMixedRealityFocusHandler
Puntatore verso il basso/Trascinato/Su/Selezionato Generato al puntatore del report, trascinare e rilasciare. IMixedRealityPointerHandler
Tocco avviato/aggiornato/completato Generato da puntatori con riconoscimento del tocco come PokePointer segnalare l'attività tocco. IMixedRealityTouchHandler

Nota

IMixedRealityFocusChangedHandler e IMixedRealityFocusHandler devono essere gestiti negli oggetti su cui vengono generati. È possibile ricevere eventi di stato attivo a livello globale, ma, a differenza di altri eventi di input, il gestore eventi globale non blocca la ricezione di eventi in base allo stato attivo (l'evento verrà ricevuto sia dal gestore globale che da un oggetto corrispondente nello stato attivo).

Eventi di input del puntatore in azione

Gli eventi di input del puntatore vengono riconosciuti e gestiti dal sistema di input MRTK in modo analogo agli eventi di input normali. La differenza è che gli eventi di input del puntatore vengono gestiti solo dal GameObject in stato attivo dal puntatore che ha generato l'evento di input, nonché da qualsiasi gestore di input globale. Gli eventi di input regolari vengono gestiti da GameObject in stato attivo per tutti i puntatori attivi.

  1. Il sistema di input MRTK riconosce che si è verificato un evento di input
  2. Il sistema di input MRTK attiva la funzione di interfaccia pertinente per l'evento di input a tutti i gestori di input globali registrati
  3. Il sistema di input determina quale GameObject è attivo per il puntatore che ha generato l'evento
    1. Il sistema di input usa il sistema eventi di Unity per attivare la funzione di interfaccia pertinente per tutti i componenti corrispondenti nel GameObject incentrato
    2. Se in qualsiasi momento un evento di input è stato contrassegnato come usato, il processo terminerà e nessun altro GameObject riceverà callback.
      • Esempio: i componenti che implementano l'interfaccia IMixedRealityFocusHandler verranno cercati un GameObject o perderanno lo stato attivo
      • Nota: il sistema eventi di Unity eseguirà una ricerca nel GameObject padre se non sono presenti componenti corrispondenti all'interfaccia desiderata nel GameObject corrente.
  4. Se non vengono registrati gestori di input globali e non viene trovato alcun GameObject con un componente/interfaccia corrispondente, il sistema di input chiamerà ogni gestore di input registrato di fallback

Esempio

Di seguito è riportato uno script di esempio che modifica il colore del renderer collegato quando un puntatore prende o lascia lo stato attivo o quando un puntatore seleziona l'oggetto.

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

Puntatori di query

È possibile raccogliere tutti i puntatori attualmente attivi eseguendo un ciclo tra le origini di input disponibili (ad esempio controller e input disponibili) per individuare i puntatori collegati.

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

Puntatore primario

Gli sviluppatori possono sottoscrivere l'evento FocusProviders PrimaryPointerChanged per ricevere una notifica quando il puntatore primario nello stato attivo è cambiato. Ciò può essere estremamente utile per identificare se l'utente sta attualmente interagendo con una scena tramite lo sguardo fisso o un raggio della mano o un'altra origine di input.

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 scena (Assets/MRTK/Examples/Demos/Input/Scenes/PrimaryPointer) mostra come usare per PrimaryPointerChangedHandler gli eventi per rispondere a un nuovo puntatore primario.

Primary Pointer Example

Risultato del puntatore

La proprietà puntatore Result contiene il risultato corrente per la query della scena usata per determinare l'oggetto con stato attivo. Per un puntatore raycast, come quelli creati per impostazione predefinita per i controller del movimento, l'input dello sguardo fisso e i raggi della mano, conterrà la posizione e la normale del raycast hit.

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 scena (Assets/MRTK/Examples/Demos/Input/Scenes/PointerResult/PointerResultExample.unity) mostra come usare il puntatore Result per generare un oggetto nella posizione di hit.

Pointer Result

Disabilitare i puntatori

Per attivare e disabilitare i puntatori (ad esempio, per disabilitare il raggio della mano), impostare per PointerBehavior un determinato tipo di puntatore tramite 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);
}

Vedere PointerUtils e TurnPointersOnOff per altri esempi.

Interazioni del puntatore tramite editor

Per gli eventi del puntatore gestiti da IMixedRealityPointerHandler, MRTK offre ulteriore praticità sotto forma di PointerHandler componente, che consente di gestire gli eventi del puntatore direttamente tramite gli eventi di Unity.

Pointer Handler

Extent puntatore

I puntatori lontani hanno impostazioni che limitano la distanza di raycast e interagire con altri oggetti nella scena. Per impostazione predefinita, questo valore è impostato su 10 metri. Questo valore è stato scelto per rimanere coerente con il comportamento della shell HoloLens.

Questa modifica può essere modificata aggiornando i DefaultControllerPointer campi del componente del ShellHandRayPointer prefab:

Extent puntatore : controlla la distanza massima con cui i puntatori interagiranno.

Extent puntatore predefinito : consente di controllare la lunghezza del raggio/linea del puntatore che verrà eseguito quando il puntatore non interagisce con alcun elemento.

Vedi anche