Puntatori - MRTK2

Puntatore

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

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

Configurazione del puntatore

I puntatori vengono configurati come parte del sistema di input in MRTK tramite un MixedRealityPointerProfileoggetto . Questo tipo di profilo viene assegnato a un MixedRealityInputSystemProfile oggetto 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 è attivo.

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

  • Puntamento di maschere di livello Raycast : si tratta di una matrice di layermasks con priorità per determinare quali possibili GameObject possono interagire con qualsiasi puntatore specificato e l'ordine di interazione da provare. Ciò può essere utile per garantire che i puntatori interagiscano prima con gli elementi dell'interfaccia utente prima di altri oggetti scena. Esempio di profilo puntatore

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.

Esempio di profilo opzioni puntatore

Ogni voce Pointer è definita dal set di dati seguente:

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

    • Ad esempio, Il PokePointer è responsabile di "poking" oggetti con un dito, ed è, per impostazione predefinita, contrassegnato come supportare solo il tipo di controller mano articolato. Viene creata un'istanza dei puntatori 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 Pointer su None la disabiliterà dal sistema in alternativa alla rimozione del puntatore dall'elenco.

  • Prefab puntatore : verrà creata un'istanza di questo asset prefab quando viene avviata la traccia di un controller corrispondente al tipo di controller e alla mano specificati.

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

Nota

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

Configurazione del cursore

Il cursore Gaze è configurabile direttamente tramite la GazeCursorPrefab proprietà all'interno MixedRealityInputSystemProfile del Editor. 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 programmazione, modificare la BaseCursor proprietà sul comportamento corrispondente IMixedRealityPointer .

Cursor Prefab, proprietà

Vedere i prefab del cursore in Assets/MRTK/SDK/Features/UX/Prefabs/Cursors per esempi di implementazioni del comportamento del cursore. In particolare, DefaultGazeCursor offre un'implementazione affidabile della modifica della grafica 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 del puntatore fornito in Assets/MRTK/SDK/Features/UX/Prefabs/Pointers contiene uno dei componenti del puntatore collegati.

Puntatori predefiniti MRTK

Puntatori lontani

LinePointer

LinePointer, una classe 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, ad ShellHandRayPointer esempio e i puntatori teletrasporto, vengono create e utilizzate (che disegnano anche linee per indicare dove finirà il teletrasporto) anziché questa classe che fornisce principalmente funzionalità comuni.

Per i controller di 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 della mano fornita dal sistema.

Linea puntatore MRTK
CurvePointer

CurvePointer estende la classe LinePointer consentendo cast di raggi in più passaggi lungo una curva. Questa classe del puntatore di base è utile per le istanze curve, ad esempio i puntatori di teletrasporto 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 Gaze/Gesture/Voice (GGV), GGVPointer alimenta le interazioni di aspetto e tocco in stile HoloLens 1, principalmente tramite l'interazione Sguardo fisso e Tocco aereo o Sguardo fisso e 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 di Unity Touch (ad esempio touchscreen). Queste sono "interazioni lontane" perché l'atto di toccare lo schermo genererà un raggio dalla fotocamera a una posizione potenzialmente lontana nella scena.

MousePointer

MousePointer alimenta uno schermo per il raycast globale per le interazioni lontane, ma per il mouse anziché il tocco.

Puntatore del mouse

Nota

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

Puntatori vicini

PokePointer

PokePointer viene usato per interagire con gli oggetti del gioco che supportano l'interazione quasi touchable. che sono GameObject con uno script collegato NearInteractionTouchable . Nel caso di UnityUI, questo puntatore cerca NearInteractionTouchableUnityUIs. PokePointer usa un spherecast per determinare l'elemento toccabile più vicino e viene usato per alimentare elementi come i pulsanti premebili.

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 tocco. Assicurarsi inoltre che i limiti del touchable corrispondano ai limiti dell'oggetto tocco.

Proprietà utili del puntatore Poke:

  • TouchableDistance: distanza massima in cui è possibile interagire con 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 per disegnare dalla punta del dito alla superficie di input attiva.
  • Maschere di livello Poke - Matrice di LayerMasks con priorità per determinare quali possibili GameObject con cui il puntatore può interagire e l'ordine di interazione da provare. Si noti che un GameObject deve avere anche un NearInteractionTouchable componente per interagire con un puntatore poke.
Puntatore Poke
SpherePointer

SpherePointer usa UnityEngine.Physics.OverlapSphere per identificare l'oggetto più vicino NearInteractionGrabbable 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 rappresenta lo NearInteractionGrabbable script.

Puntatore afferra

Proprietà utili del puntatore sphere:

  • Raggio cast sfera: raggio per la sfera usata per eseguire query per oggetti afferrabili.
  • Margine oggetto vicino: distanza sopra il raggio cast della sfera da eseguire per eseguire una query per rilevare se un oggetto si trova vicino al puntatore. Total Near Object detection radius is Sphere Cast Radius + Near Object Margin
  • Angolo settore oggetti vicino: angolo intorno all'asse in avanti del puntatore per l'esecuzione di query per gli oggetti vicini. Rende la funzione di IsNearObject query come un cono. Questo valore è impostato su 66 gradi per impostazione predefinita in modo che corrisponda al comportamento di Hololens 2

Puntatore sphere modificato per eseguire query solo per gli oggetti nella direzione in avanti

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

    Nota

    Il livello 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 di sfere con la mesh spaziale. È possibile abilitarlo modificando il prefab GrabPointer.

  • Ignore Colliders Not in FOV ( Ignora collisori non in FOV ): indica se ignorare i collisori che potrebbero trovarsi vicino al puntatore, ma non nell'oggetto FOV visivo. Questo può impedire afferramenti accidentali e consentirà ai raggi della mano di accendersi quando si può 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 di visualizzazione (o FOV verticale).
Puntatore a sfera

Puntatori teletrasporto

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

Supporto dei puntatori per le piattaforme di realtà mista

La tabella seguente illustra 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 Valevole Valevole Valevole
TeleportPointer Valevole Valevole
GGVPointer Valevole
SpherePointer Valevole
PokePointer Valevole

Interazioni puntatore tramite codice

Interfacce degli eventi puntatore

MonoBehaviours che implementa una o più delle interfacce seguenti e vengono assegnate a un GameObject con un Collider riceverà gli eventi di interazioni puntatore definiti dall'interfaccia associata.

Evento Descrizione Gestore
Prima della modifica dello stato attivo/della modifica dello stato attivo Generato sia sull'oggetto di gioco che sulla perdita dello stato attivo e su quello che lo guadagna ogni volta che un puntatore cambia lo stato attivo. IMixedRealityFocusChangedHandler
Messa a fuoco Invio/Uscita Generato sull'oggetto di gioco che ottiene lo stato attivo quando il primo puntatore entra in esso e su quello che perde lo stato attivo quando l'ultimo puntatore lo lascia. IMixedRealityFocusHandler
Puntatore verso il basso/Trascinato/Su/Cliccato Generato per la pressione, il trascinamento e il rilascio del puntatore del report. IMixedRealityPointerHandler
Tocco avviato/aggiornato/completato Generato da puntatori in grado di riconoscere il tocco, ad esempio PokePointer per segnalare l'attività di tocco. IMixedRealityTouchHandler

Nota

IMixedRealityFocusChangedHandler e IMixedRealityFocusHandler devono essere gestiti negli oggetti in 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 regolari. La differenza è che gli eventi di input del puntatore vengono gestiti solo da GameObject nello stato attivo dal puntatore che ha generato l'evento di input, nonché da eventuali gestori di input globali. Gli eventi di input regolari vengono gestiti da GameObject nello 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 nell'oggetto 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: ai componenti che implementano l'interfaccia IMixedRealityFocusHandler verrà eseguita la ricerca di un GameObject che ottiene o perde lo stato attivo
      • Nota: il sistema eventi Unity verrà visualizzato per cercare l'oggetto GameObject padre se non vengono trovati componenti corrispondenti all'interfaccia desiderata nell'oggetto 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 assume 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 i controller e gli input disponibili, per individuare i puntatori a cui sono 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, 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 gli PrimaryPointerChangedHandler eventi for per rispondere a un nuovo puntatore primario.

Esempio di puntatore primario

Risultato del puntatore

La proprietà pointer Result contiene il risultato corrente per la query della scena utilizzata per determinare l'oggetto con lo stato attivo. Per un puntatore raycast, come quelli creati per impostazione predefinita per i controller di movimento, l'input dello sguardo fisso e i raggi della mano, conterrà la posizione e la normale dell'hit 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 scena (Assets/MRTK/Examples/Demos/Input/Scenes/PointerResult/PointerResultExample.unity) mostra come usare il puntatore Result per generare un oggetto nella posizione di hit.

Risultato puntatore

Disabilitare i puntatori

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

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

Gestore puntatore

Extent del puntatore

I puntatori lontani hanno impostazioni che limitano la distanza in cui eseguiranno il raycast e interagiranno 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 operazione 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 : controlla la lunghezza del raggio/linea del puntatore di cui verrà eseguito il rendering quando il puntatore non interagisce con nulla.

Vedere anche