Ukazatele – MRTK2
Tento článek vysvětluje, jak v praxi nakonfigurovat vstup ukazatele a reagovat na ně. Pokud chcete lépe porozumět tomu, jak ovládat více ukazatelů na vysoké úrovni, přečtěte si téma Architektura ukazatele.
Při zjištění nového kontroleru se ukazatele automaticky vytvoří za běhu. K ovladači lze připojit více než jeden ukazatel. Například s výchozím profilem ukazatele získá Windows Mixed Reality kontrolery jak čáru, tak parabolický ukazatel pro normální výběr a teleportaci.
Konfigurace ukazatele
Ukazatele jsou nakonfigurovány jako součást vstupního systému v MRTK prostřednictvím MixedRealityPointerProfile
. Tento typ profilu je přiřazen k objektu MixedRealityInputSystemProfile
v inspektoru konfigurace MRTK. Profil ukazatele určuje kurzor, typy ukazatelů, které jsou k dispozici za běhu, a způsob vzájemné komunikace těchto ukazatelů, aby se rozhodl, který z nich je aktivní.
Pointing Extent – definuje maximální vzdálenost, po kterou může ukazatel interagovat s objektem GameObject.
Namíření raycastových masek vrstvy – Toto je pole vrstvových masek podle priority, které určuje, se kterými možnými objekty GameObjects může daný ukazatel interagovat, a pořadí, ve kterém se má pokusit o interakci. To může být užitečné, pokud chcete zajistit, aby ukazatele nejprve interagovali s prvky uživatelského rozhraní před ostatními objekty scény.
Konfigurace možností ukazatele
Výchozí konfigurace profilu ukazatele MRTK zahrnuje následující třídy ukazatelů a přidružené předem připravené objekty. Seznam ukazatelů dostupných pro systém za běhu je definován v části Možnosti ukazatele v profilu ukazatele. Vývojáři můžou tento seznam využít k překonfigurování existujících ukazatelů, přidání nových ukazatelů nebo k jejich odstranění.
Každá položka ukazatele je definována následující sadou dat:
Typ kontroleru – sada kontrolerů, pro které je ukazatel platný.
- Například PokePointer je zodpovědný za "šťouchnutí" objektů prstem a je ve výchozím nastavení označen pouze jako podpůrný typ kloubového ovladače rukou. Ukazatele se vytvářejí pouze v případě, že je k dispozici kontroler, a zejména typ kontroleru definuje, s jakými řadiči lze tento prefab ukazatele vytvořit.
Handness – umožňuje vytvořit instanci ukazatele jenom pro určitou ruku (vlevo/vpravo).
Poznámka
Nastavením vlastnosti Odevzdání položky ukazatele na hodnotu None ji v podstatě zakážete ze systému jako alternativu k odebrání tohoto ukazatele ze seznamu.
- Prefab pointer – tento prefab asset se vytvoří, když se začne sledovat kontroler odpovídající zadanému typu kontroleru a odevzdání.
K kontroleru je možné přidružit více ukazatelů. Například v DefaultHoloLens2InputSystemProfile
systému (Assets/MRTK/SDK/Profiles/HoloLens2/) je kloubový ovladač ruky přidružený k pokePointeru, GrabPointeru a DefaultControllerPointeru (tj. paprskům rukou).
Poznámka
MRTK poskytuje sadu prefab ukazatelů v assets/MRTK/SDK/Features/UX/Prefabs/Pointers. Nový vlastní prefab lze sestavit, pokud obsahuje jeden ze skriptů ukazatele v Assets/MRTK/SDK/Features/UX/Scripts/Pointers nebo jiném skriptu implementované IMixedRealityPointer
.
Konfigurace kurzoru
Kurzor pohledu je přímo konfigurovatelný prostřednictvím GazeCursorPrefab
vlastnosti v editoru MixedRealityInputSystemProfile
. Pokud chcete nakonfigurovat kurzor použitý pro jiné ukazatele, musíte změnit prefab použitý v CursorPrefab
poli odpovídajícího BaseControllerPointer
. Chcete-li změnit kurzor programově, upravte BaseCursor
vlastnost odpovídajícího IMixedRealityPointer
chování.
Příklady implementace chování kurzoru najdete v tématu Assets/MRTK/SDK/Features/UX/Prefabs/Cursors . Konkrétně DefaultGazeCursor poskytuje robustní implementaci změny grafiky kurzoru na základě kontextového stavu.
Výchozí třídy ukazatelů
Následující třídy jsou předdefinované ukazatele MRTK, které jsou k dispozici a definované ve výchozím profilu ukazatele MRTK uvedeném výše. Každý prefab ukazatele zadaný v části Assets/MRTK/SDK/Features/UX/Prefabs/Pointers obsahuje jednu z připojených komponent ukazatele.
Ukazatele na dálku
LinePointer
LinePointer, třída základního ukazatele, nakreslí čáru ze zdroje vstupu (tj. kontroleru) ve směru ukazatele a podporuje jeden paprsek v tomto směru. Obecně platí, že podřízené třídy, jako ShellHandRayPointer
jsou ukazatele teleportu a , se vytvářejí a využívají (které také kreslí čáry, které označují, kde teleportace skončí) místo této třídy, která primárně poskytuje společné funkce.
U ovladačů pohybu, jako jsou Oculus, Vive a Windows Mixed Reality, bude rotace odpovídat otáčení ovladače. U jiných ovladačů, jako jsou HoloLens 2 kloubové ruce, odpovídá otáčení polohovací pozici ruky poskytované systémem.
CurvePointer
CurvePointer rozšiřuje třídu LinePointer tím, že umožňuje vícekrokové paprskové přetypování podél křivky. Tato základní třída ukazatele je užitečná pro zakřivené instance, jako jsou teleportační ukazatele, kde se čára konzistentně ohýbá do paraboly.
ShellHandRayPointer
Implementace ShellHandRayPointer, která se rozšiřuje od LinePointer
, se používá jako výchozí pro profil ukazatele MRTK. Prefab DefaultControllerPointer implementuje ShellHandRayPointer
třídu.
GGVPointer
GGVPointer, který se také označuje jako ukazatel pohledu/gesta/hlasu (GGV), podporuje vzhled HoloLensu ve stylu 1 a interakce klepnutí, a to především prostřednictvím pohledu a klepnutí vzduchem nebo interakce pohledu a hlasového výběru. Poloha a směr ukazatele GGV je řízen polohou a otáčením hlavy.
TouchPointer
TouchPointer je zodpovědný za práci se vstupem Unity Touch (tj. dotykovým displejem). Jedná se o "vzdálené interakce", protože když se dotknete obrazovky, vysadí se paprsek z fotoaparátu na potenciálně vzdálené místo ve scéně.
MousePointer
Myš MousePointer nasměruje obrazovku na svět raycast pro vzdálené interakce, ale pro myš místo dotykového ovládání.
Poznámka
Podpora myši není ve výchozím nastavení v MRTK dostupná, ale je možné ji povolit přidáním nového zprostředkovatele vstupních dat typu MouseDeviceManager
do vstupního profilu MRTK a přiřazením MixedRealityMouseInputProfile
zprostředkovatele dat.
Blízké ukazatele
PokePointer
PokePointer se používá k interakci s herními objekty, které podporují "blízkou interakci dotykového ovládání". což jsou Objekty GameObjects s připojeným NearInteractionTouchable
skriptem. V případě UnityUI tento ukazatel hledá NearInteractionTouchableUnityUIs. PokePointer používá SphereCast k určení nejbližšího dotykového prvku a slouží k napájení věcí, jako jsou stisknutelná tlačítka.
Při konfiguraci objektu GameObject s komponentou NearInteractionTouchable
nezapomeňte nakonfigurovat parametr localForward tak, aby odkazoval mimo přední stranu tlačítka nebo jiného objektu, který by měl být dotykový. Také se ujistěte, že hranice dotykového objektu odpovídají hranicím dotykového objektu.
Užitečné vlastnosti ukazatele poke:
- TouchableDistance: Maximální vzdálenost, ve které lze s dotykovým povrchem pracovat
- Vizuály: Herní objekt používaný k vykreslení vizuálu prstu (prsten na prstu, ve výchozím nastavení).
- Čára: Volitelná čára pro kreslení z prstu na aktivní vstupní plochu.
- Poke Layer Masks – pole vrstvových masek s prioritou, které určuje, se kterými možnými objekty GameObject může ukazatel interagovat, a pořadí, ve kterém se má pokusit o interakci. Všimněte si, že GameObject musí mít také komponentu
NearInteractionTouchable
, aby bylo možné pracovat s ukazatelem poke.
SpherePointer
SpherePointer používá UnityEngine.Physics.OverlapSphere k identifikaci nejbližšího NearInteractionGrabbable
objektu pro interakci, což je užitečné pro "grabbable" vstup, jako ManipulationHandler
je . Podobně jako u funkčního PokePointer
/NearInteractionTouchable
páru musí herní objekt obsahovat komponentu NearInteractionGrabbable
, která je skriptem, aby bylo možné pracovat s ukazatelem koule.
Užitečné vlastnosti ukazatele koule:
- Poloměr přetypování koule: Poloměr koule použité k dotazování na uchopitelné objekty.
- Blízko okraje objektu: Vzdálenost v horní části poloměru přetypování sphere, která se má dotazovat na zjištění, jestli je objekt v blízkosti ukazatele. Total Near Object detection radius is Sphere Cast Radius + Near Object Margin
- Úhel v blízkosti sektoru objektu: Úhel kolem dopředu osy ukazatele pro dotazování na blízké objekty.
IsNearObject
Vytvoří funkci dotazu jako kužel. Tato hodnota je ve výchozím nastavení nastavená na 66 stupňů, aby odpovídala chování Hololens 2.
- Faktor vyhlazování blízko objektu: Faktor vyhlazování pro detekci blízkých objektů. Pokud je v poloměru blízkého objektu zjištěn objekt, dotazovaný poloměr se pak změní na Poloměr blízko objektu * (1 + faktor vyhlazování blízkého objektu), aby se snížila citlivost a ztížila se pro objekt opustit rozsah detekce.
- Uchopte masky vrstvy – pole vrstvových masek s prioritou, které určuje, se kterými možnými objekty GameObject může ukazatel interagovat, a pořadí, ve kterém se má pokusit o interakci. Všimněte si, že objekt GameObject musí mít také objekt
NearInteractionGrabbable
pro interakci s SpherePointerem.Poznámka
Vrstva prostorového povědomí je ve výchozím prefabu GrabPointeru poskytovaném MRTK zakázaná. To se provádí za účelem snížení dopadu na výkon při provádění dotazu překrývajícího se s prostorovou sítí. Můžete to povolit úpravou prefabu GrabPointer.
- Ignore Colliders Not in FOV – Jestli se mají ignorovat kolidátory, které se můžou blížit ukazateli, ale ve skutečnosti ne ve vizuálu FOV. To může zabránit náhodnému uchopení a umožní zapnutí paprsků rukou, když můžete být blízko uchopení, ale nevidíte ho. Vizuální FOV se z důvodů výkonu definuje prostřednictvím kuželu místo typického frustum. Tento kužel je zarovnaný na střed a orientaci stejně jako frustum fotoaparátu s poloměrem, který se rovná polovině výšky displeje (neboli svislé FOV).
Teleportování ukazatelů
TeleportPointer
aplikace vyvolá žádost o teleport, když se provede akce (tj. stisknete tlačítko teleportu), aby se uživatel mohl přesunout.ParabolicTeleportPointer
vyvolá žádost o teleport, když je provedena akce (tj. je stisknuto tlačítko teleportu) s parabolickým paprskovým paprskem, aby bylo možné uživatele přesunout.
Podpora ukazatelů pro platformy hybridní reality
Následující tabulka obsahuje podrobnosti o typech ukazatelů, které se obvykle používají pro běžné platformy v MRTK. POZNÁMKA: Na tyto platformy je možné přidat různé typy ukazatelů. Do virtuální reality můžete například přidat ukazatel Poke nebo Sphere. Kromě toho můžou zařízení VR s gamepadem používat ukazatel GGV.
Ukazatel | OpenVR | Windows Mixed Reality | HoloLens 1 | HoloLens 2 |
---|---|---|---|---|
ShellHandRayPointer | Platné | Platné | Platné | |
TeleportPointer | Platné | Platné | ||
GGVPointer | Platné | |||
SpherePointer | Platné | |||
PokePointer | Platné |
Interakce s ukazateli prostřednictvím kódu
Rozhraní událostí ukazatele
MonoBehaviours, které implementují jedno nebo více z následujících rozhraní a jsou přiřazeny GameObject s Collider
a budou přijímat události Interakce Ukazatele definované přidružené rozhraní.
Událost | Popis | Obslužná rutina |
---|---|---|
Před změnou fokusu / Změna fokusu | Vyvoláno při ztrátě fokusu na herním objektu i na objektu, který ho získává pokaždé, když ukazatel změní fokus. | IMixedRealityFocusChangedHandler |
Vstup/ ukončení fokusu | Aktivováno na herním objektu, který získává fokus, když do něj vstoupí první ukazatel, a na jednom, který fokus ztratí, když ho poslední ukazatel opustí. | IMixedRealityFocusHandler |
Ukazatel dolů / přetažení / nahoru / kliknutí | Zvednuté na ukazatel sestavy stiskněte, přetáhněte ho a uvolněte. | IMixedRealityPointerHandler |
Dotykové ovládání spuštěno / aktualizováno / dokončeno | Uchycené ukazateli pracujícími s dotykovým ovládáním, jako PokePointer by oznamovaly aktivitu dotykového ovládání. |
IMixedRealityTouchHandler |
Poznámka
IMixedRealityFocusChangedHandler
a IMixedRealityFocusHandler
by měly být zpracovány v objektech, na které jsou vyvolány. Události fokusu je možné přijímat globálně, ale na rozdíl od jiných vstupních událostí globální obslužná rutina událostí neblokuje příjem událostí na základě fokusu (událost přijme globální obslužná rutina i odpovídající objekt v fokusu).
Události vstupu ukazatele v akci
Vstupní události ukazatele jsou rozpoznány a zpracovávány vstupním systémem MRTK podobným způsobem jako běžné vstupní události. Rozdíl je v tom, že události vstupu ukazatele jsou zpracovávány pouze objektem GameObject v fokusu ukazatelem, který aktivoval vstupní událost, stejně jako jakékoli globální obslužné rutiny vstupu. Běžné vstupní události jsou zpracovávány objekty GameObject fokus pro všechny aktivní ukazatele.
- Vstupní systém MRTK rozpozná vstupní událost, ke které došlo.
- Vstupní systém MRTK aktivuje příslušnou funkci rozhraní pro vstupní událost všem registrovaným globálním obslužným rutinám vstupu.
- Vstupní systém určuje, na který objekt GameObject je fokus pro ukazatel, který aktivoval událost.
- Vstupní systém využívá Event System Unity k vyvolání příslušné funkce rozhraní pro všechny odpovídající komponenty na zaměřeném Objektu GameObject.
- Pokud byla vstupní událost v libovolném okamžiku označena jako použitá, proces se ukončí a žádné další objekty GameObject nebudou přijímat zpětná volání.
- Příklad: Komponenty implementované rozhraní
IMixedRealityFocusHandler
budou vyhledána pro GameObject získá nebo ztratí fokus. - Poznámka: Pokud se v aktuálním objektu GameObject nenajdou žádné komponenty odpovídající požadovanému rozhraní, bude Unity Event System prohledat nadřazený objekt GameObject.
- Příklad: Komponenty implementované rozhraní
- Pokud nejsou zaregistrované žádné obslužné rutiny globálního vstupu a nenajde se žádný objekt GameObject s odpovídající komponentou nebo rozhraním, vstupní systém zavolá každou obslužnou rutinu vstupu zaregistrovanou pro náhradní použití.
Příklad
Níže je příklad skriptu, který změní barvu připojeného vykreslovacího modulu, když ukazatel převezme nebo opustí fokus nebo když ukazatel vybere objekt.
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;
}
}
Ukazatele dotazů
Je možné shromáždit všechny ukazatele, které jsou aktuálně aktivní, pomocí smyčky mezi dostupnými vstupními zdroji (tj. ovladači a dostupnými vstupy) a zjistit, které ukazatele jsou k nim připojeny.
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);
}
}
}
Primární ukazatel
Vývojáři se mohou přihlásit k odběru FocusProviders PrimaryPointerChanged událostí být upozorněni, když se primární ukazatel v fokusu změnil. To může být velmi užitečné, pokud chcete zjistit, jestli uživatel právě komunikuje se scénou pohledem, paprskem ruky nebo jiným vstupním zdrojem.
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);
}
Scéna PrimaryPointerExample
(Assets/MRTK/Examples/Demos/Input/Scenes/PrimaryPointer) ukazuje, jak použít PrimaryPointerChangedHandler
pro události k reakci na nový primární ukazatel.
Výsledek ukazatele
Vlastnost ukazatele Result
obsahuje aktuální výsledek pro dotaz scény použitý k určení objektu s fokusem. U ukazatele raycastu, jako jsou ty, které jsou ve výchozím nastavení vytvořeny pro ovladače pohybu, vstup pohledu a paprsky rukou, bude obsahovat umístění a normální stav raycastu.
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);
}
Scéna PointerResultExample
(Assets/MRTK/Examples/Demos/Input/Scenes/PointerResult/PointerResultExample.unity) ukazuje, jak použít ukazatel Result
k vytvoření objektu v umístění, kde byl nalezen.
Zakázat ukazatele
Pokud chcete zapnout a zakázat ukazatele (například zakázat paprsek ruky), nastavte PointerBehavior
pro daný typ ukazatele pomocí 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);
}
Další příklady najdete v tématu PointerUtils
a TurnPointersOnOff
.
Interakce s ukazateli prostřednictvím editoru
Pro události ukazatele zpracovávané nástrojem IMixedRealityPointerHandler
poskytuje MRTK další pohodlí ve formě PointerHandler
komponenty, která umožňuje zpracování událostí ukazatele přímo prostřednictvím událostí Unity.
Rozsah ukazatele
Daleko ukazatele mají nastavení, která omezují, jak daleko budou provádět raycast a komunikovat s jinými objekty ve scéně. Ve výchozím nastavení je tato hodnota nastavená na 10 metrů. Tato hodnota byla zvolena tak, aby zůstala konzistentní s chováním prostředí HoloLens.
To lze změnit aktualizací DefaultControllerPointer
polí komponenty prefab ShellHandRayPointer
:
Rozsah ukazatele – určuje maximální vzdálenost, se kterou budou ukazatele interagovat.
Výchozí rozsah ukazatele – určuje délku paprsku nebo čáry ukazatele, který se vykreslí, když ukazatel s ničím nepracuje.