Puntatori - MRTK2
Questo articolo illustra come configurare e rispondere all'input del puntatore in pratica. Per comprendere meglio come controllare più puntatori a livello generale, vedere Architettura puntatore.
I puntatori vengono istanza automaticamente in fase di esecuzione quando viene rilevato un nuovo controller. Più puntatori possono essere collegati a un controller. Ad esempio, con il profilo del puntatore predefinito, Windows Mixed Reality controller ottengono rispettivamente una riga e un puntatore parabolico per la selezione normale e il teleportazione.
Configurazione 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 è attivo.
Estensione puntatore : definisce la distanza massima per cui un puntatore può interagire con un GameObject.
Puntatore a Raycast Layer Masks : si tratta di una matrice con priorità di LayerMasks per determinare quali possibili oggetti GameObjects possono interagire con e l'ordine di interazione da tentare. Ciò può essere utile per garantire che i puntatori interagiscono con gli elementi dell'interfaccia utente prima di altri oggetti scena.
Configurazione delle opzioni del puntatore
La configurazione predefinita del profilo del puntatore MRTK include le classi del puntatore seguenti e i prefab associati out-of-box. 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.
Ogni voce puntatore è definita dal set di dati seguente:
Tipo di controller : set di controller per cui un puntatore è valido.
- Ad esempio, Il PokePointer è responsabile degli 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.
Handness : 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 None la disabilita dal sistema come alternativa alla rimozione di tale puntatore dall'elenco.
- Prefab puntatore : questo asset prefab verrà creata un'istanza quando un controller corrispondente al tipo di controller specificato e la mano inizia a essere monitorato.
È possibile avere più puntatori associati a un controller. Ad esempio, in DefaultHoloLens2InputSystemProfile
(Assets/MRTK/SDK/Profiles/HoloLens2/) il controller di mano articolato è associato al pokePointer, GrabPointer e defaultControllerPointer (ad esempio i raggi di mano).
Nota
MRTK fornisce un set di prefab puntatori in Asset/MRTK/SDK/Features/UX/Prefabs/Puntatori. Un nuovo prefab personalizzato può essere compilato purché contenga uno degli script puntatori in Asset/MRTK/SDK/Features/UX/Script/Puntatori o qualsiasi altro script che implementa IMixedRealityPointer
.
Configurazione del cursore
Il cursore Sguardo è configurabile direttamente tramite la GazeCursorPrefab
proprietà MixedRealityInputSystemProfile
nell'editor. Per configurare il cursore usato per altri puntatori, è necessario modificare il prefab usato nel CursorPrefab
campo del corrispondente BaseControllerPointer
. Per modificare il programma di cursore, modificare la BaseCursor
proprietà nel comportamento corrispondente IMixedRealityPointer
.
Vedere i prefab del cursore in Asset/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 Asset/MRTK/SDK/Features/UX/Prefabs/Pointers contiene uno dei componenti del puntatore collegati.
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 come e ShellHandRayPointer
i puntatori di teleporto vengono create e usate (che disegnano anche linee per indicare dove la teleportazione finirà in corrispondenza) 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 puntante fornita dal sistema della mano.
CurvePointer
CurvePointer estende la classe LinePointer consentendo cast a raggi a più passaggi lungo una curva. Questa classe puntatore di base è utile per le istanze curve, ad esempio i puntatori di teleportazione in cui la linea si piega in modo coerente in una parabola.
ShellHandRayPointer
L'implementazione di ShellHandRayPointer, che si estende da LinePointer
, viene usata come impostazione predefinita per il profilo del puntatore MRTK. Il prefab DefaultControllerPointer implementa la ShellHandRayPointer
classe.
GGVPointer
Noto anche come puntatore Gaze/Gesture/Voice (GGV), il GGVPointer abilita l'aspetto di HoloLens 1 e tocca le interazioni, principalmente tramite Gaze e Air Tap o Gaze e voice Select interazione. 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 casterà un raggio dalla fotocamera a una posizione potenzialmente lontana nella scena.
MousePointer
MousePointer consente a uno schermo di visualizzare il raycast mondiale per interazioni lontane, ma per il mouse invece del tocco.
Nota
Il supporto del mouse non è disponibile per impostazione predefinita in MRTK, ma può essere abilitato aggiungendo un nuovo provider MouseDeviceManager
di dati di input al profilo di input MRTK e assegnandolo MixedRealityMouseInputProfile
al provider di dati.
Puntatori vicino
PokePointer
Il PokePointer viene usato per interagire con gli oggetti del gioco che supportano "near interaction touchable". che sono GameObjects che hanno uno script collegato NearInteractionTouchable
. Nel caso di UnityUI, questo puntatore cerca NearInteractionTouchableUnityUIs. Il PokePointer usa un oggetto SphereCast per determinare l'elemento touchable più vicino e viene usato per attivare elementi come i pulsanti premuti.
Quando si configura GameObject con il componente, assicurarsi di configurare il NearInteractionTouchable
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 in cui è possibile interagire con una superficie toccabile
- Oggetti visivi: oggetto Game usato per eseguire il rendering dell'oggetto visivo della punta del dito (l'anello sul dito, per impostazione predefinita).
- Linea: linea facoltativa da disegnare dalla dita alla superficie di input attiva.
- Maschera di livello poke : matrice con priorità di LayerMasks per determinare quali possibili oggetti GameObject possono interagire con e l'ordine di interazione da tentare. Si noti che un GameObject deve avere anche un componente per interagire con un
NearInteractionTouchable
puntatore poke.
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 interagire con il puntatore Sphere, l'oggetto gioco deve contenere un componente che è lo NearInteractionGrabbable
script.
Proprietà utili del puntatore sphere:
- Raggio cast della sfera: raggio per la sfera usata per eseguire query per oggetti afferrabili.
- Near Object Margin: distanza superiore al raggio cast sphere per eseguire una query per rilevare se un oggetto è vicino al puntatore. Il raggio totale di rilevamento di oggetti vicino è Raggio cast sphere + Margine oggetto vicino
- Angolo del settore dell'oggetto vicino: angolo intorno all'asse avanti del puntatore per la query per gli oggetti vicini. Rende la
IsNearObject
funzione di query come un cono. Questo valore è impostato su 66 gradi per impostazione predefinita in modo che corrisponda al comportamento di Hololens 2
- Fattore di smoothing dell'oggetto vicino: fattore di smoothing per il rilevamento di oggetti vicini. Se un oggetto viene rilevato nel raggio dell'oggetto vicino, il raggio sottoposto a query diventa Near Object Radius * (1 + Near Object Smoothing Factor) per ridurre la sensibilità e rendere più difficile un oggetto lasciare l'intervallo di rilevamento.
- Grab Layer Masks : matrice con priorità di LayerMasks per determinare quali possibili oggetti GameObject possono interagire con e l'ordine di interazione da tentare. Si noti che un GameObject deve avere anche un
NearInteractionGrabbable
oggetto per interagire con un Oggetto SpherePointer.Nota
Il livello di consapevolezza spaziale è disabilitato nel prefab di GrabPointer predefinito fornito da MRTK. Questa operazione consente di ridurre l'impatto sulle prestazioni dell'esecuzione di una query di sovrapposizione della sfera con la mesh spaziale. È possibile abilitare questa operazione modificando il prefab di GrabPointer.
- Ignora colliders Non in FOV: se ignorare i collideri che potrebbero essere vicini al puntatore, ma non in realtà nel FOV visivo. Ciò può impedire afferramenti accidentali e permetterà ai raggi della mano di attivare 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).
Puntatori teleporti
TeleportPointer
genererà una richiesta di teleporto quando viene eseguita un'azione (ad esempio il pulsante di teleporto viene premuto) per spostare l'utente.ParabolicTeleportPointer
genererà una richiesta di teleporto quando viene eseguita un'azione (ad esempio il pulsante di teleporto viene premuto) con un raycast linea parabolico per spostare l'utente.
Supporto puntatore per piattaforme di realtà mista
Nella tabella seguente vengono descritti i tipi di puntatore usati in genere per le piattaforme comuni in MRTK. NOTA: è possibile aggiungere diversi tipi di puntatore a queste piattaforme. Ad esempio, è possibile aggiungere un puntatore Poke o un puntatore Sphere a VR. Inoltre, i dispositivi VR con un gamepad possono 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 assegnate a un GameObject con un Collider
oggetto riceverà eventi di interazione 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 lo entra e su uno perde lo stato attivo quando l'ultimo puntatore lo lascia. | IMixedRealityFocusHandler |
Puntatore verso il basso/Trascinato/Verso l'alto/Fare clic su | Generato in puntatore di report premere, trascinare e rilasciare. | IMixedRealityPointerHandler |
Tocco avviato/aggiornato/completato | Generato dai puntatori a riconoscimento del tocco come PokePointer segnalare l'attività tocco. |
IMixedRealityTouchHandler |
Nota
IMixedRealityFocusChangedHandler
e IMixedRealityFocusHandler
deve essere gestito 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 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 dal GameObject in stato attivo dal puntatore che ha attivato l'evento di input, nonché da tutti i gestori di input globali. Gli eventi di input regolari vengono gestiti da GameObjects nello stato attivo per tutti i puntatori attivi.
- Il sistema di input MRTK riconosce che si è verificato un evento di input
- Il sistema di input MRTK attiva la funzione di interfaccia pertinente per l'evento di input a tutti i gestori di input globali registrati
- Il sistema di input determina quale GameObject è attivo per il puntatore che ha attivato l'evento
- 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
- Se in qualsiasi momento un evento di input è stato contrassegnato come usato, il processo terminerà e non verranno ricevuti altri CallObjects.
- Esempio: i componenti che implementano l'interfaccia
IMixedRealityFocusHandler
verranno cercati per ottenere un GameObject o perdere lo stato attivo - Nota: il sistema eventi unity verrà visualizzato in modo da cercare GameObject padre se non sono presenti componenti corrispondenti all'interfaccia desiderata nell'oggetto GameObject corrente.
- Esempio: i componenti che implementano l'interfaccia
- Se non vengono registrati gestori di input globali e non viene trovato GameObject con un componente/interfaccia corrispondente, il sistema di input chiamerà ogni gestori di input registrati di fallback
Esempio
Di seguito è riportato uno script di esempio che modifica il colore del renderer collegato quando un puntatore accetta 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 il ciclo attraverso le origini di input disponibili (ad esempio controller e input disponibili) per individuare quali puntatori sono collegati a loro.
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 interagisce con una scena tramite lo sguardo o un raggio di 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 (Asset/MRTK/Esempi/Demos/Input/Scene/PrimaryPointer) mostra come usare gli PrimaryPointerChangedHandler
eventi per rispondere a un nuovo puntatore primario.
Risultato puntatore
La proprietà puntatore Result
contiene il risultato corrente per la query della scena usata 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 e i raggi della mano, conterrà la posizione e la normalità 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.
Disabilitare i puntatori
Per attivare e disabilitare i puntatori (ad esempio, per disabilitare il raggio della mano), impostare l'oggetto 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);
}
Per altri esempi, 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 unity.
Estensione puntatore
I puntatori lontani hanno impostazioni che limitano la distanza in cui verranno raggicast e interagiscono 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:
Estensione puntatore : consente di controllare la distanza massima con cui i puntatori interagiscono.
Estensione puntatore predefinita : consente di controllare la lunghezza del raggio/riga del puntatore che eseguirà il rendering quando il puntatore non interagisce con nulla.