Interaktionsarkitektur – MRTK3
MRTK bygger på den uppsättning interaktionsfunktioner som erbjuds av Unitys XR Interaction Toolkit. Funktioner för mixad verklighet som artikulerad handspårning, blick och nyp kräver mer avancerade interagerare än den uppsättning som tillhandahålls med XRI som standard. MRTK definierar nya interaktionsgränssnitt, kategoriserade i allmänhet efter indatamodalitet och motsvarande implementeringar.
Sammanfattning och granskning
För utvecklare som är nybörjare på XRI rekommenderar vi att du först läser dokumentationen för Unitys XRI-arkitektur. MRTK-interagerare är underklasser av befintliga XRI-interaktionsmän eller implementeringar av XRI-interaktionsgränssnitten. Se Unitys dokumentation om deras interaktionsarkitektur som även gäller för MRTK.
Goda medborgare i XRI
De anpassade MRTK-interagerarna är väluppfostrade med avseende på standardgränssnitten för XRI-interaktionsorn. ur XRI-systemens perspektiv är de oskiljbara från "vanilj"-interaktionsfaktorer. Inversen är också sann; När du skapar avancerade interaktionsbara objekt i MRTK fungerar standard-XRI-interaktionsfunktionerna fortfarande för grundläggande hovring och val. Det är en del av MRTK:s arbete med att vara helt kompatibelt med befintliga XRI-projekt. Om du har ett XRI-program fungerar MRTK-interaktions- och användargränssnittskontroller med din befintliga "vanilj" XRI-konfiguration.
Abstraktion av indatamodalitet
Indataenheten, interageraren som utför interaktionen och de interaktionshändelser som de genererar är alla arkitektoniskt isolerade i XRI. Den här isoleringen är viktig för indataabstraktionsstrategin i MRTK3 och gör att vi kan skriva plattformsoberoende och enhetsöverskridande interaktioner som fungerar bra i alla kontexter.
Från MRTK v2 finns det en vanlig instinkt att koda interaktioner som är specifika för en viss indatatyp eller enhet. Många utvecklare är vana vid att skriva interaktioner som reagerar specifikt på ett nära grepp, en lång stråle eller någon annan specifik indatatyp.
Mrtk3 möjliggör fortfarande tvetydighet och identifiering av enskilda indatalägen, men hårdkodande interaktioner med specifika enskilda indatatyper begränsar artificiellt och minskar flexibiliteten i dina interaktioner. Mer information om detta finns i dokumentationen om interaktionsbar arkitektur, men nyckeln för interaktionsfaktorer är att de i allmänhet inte behöver mappa 1:1 med indataenheter.
AttachTransform och Inversion av kontroll
Mycket av vad MRTK v2 gjorde i "flytta logik" som en del av ObjectManipulator
, Slider
och så vidare, är nu själva interaktionsorns ansvar. Interageraren styr nu dess attachTransform för att definiera hur en viss typ av manipulering fungerar. Man behöver inte längre skriva komplex interaktionslogik på den interaktionsbara logik som skiljer sig mellan indatamodaliteter. I stället kan din enhetliga manipulationslogik lyssna på "s"-attityden attachTransform
oavsett indatamodalitet eller enheten som kör den.
Till exempel finns ett GrabInteractor
's attachTransform
vid grepppunkten på handen/styrenheten. En XRRayInteractor
's attachTransform
ligger vid träffpunkten vid strålens slut. ' CanvasProxyInteractor
s attachTransform
finns där musen har klickat. För alla dessa olika interaktionsfaktorer behöver den interagerande inte bry sig om typen av interagerare för att kunna svara korrekt på manipulationer.
De interagerande frågorna attachTransform
och kan behandla var attachTransform
och en av dem oavsett interaktionstyp.
Den här metoden är viktig för kompatibilitet med befintliga XRI-interaktionsfaktorer och för att kunna framtidssäkra dina interaktioner för indatamodaliteter som ännu inte har utvecklats. Om en ny indatametod introduceras behöver du inte ändra befintliga interaktionsbara objekt om den nya interaktionsorn genererar en giltig och väluppfostrad attachTransform
.
Det är alltså, filosofiskt, attachTransform
interaktionslogik. För alla anpassade interaktioner bör du alltid prioritera att skriva en ny interaktion med ny attachTransform
logik i stället för att skriva om eller utöka interaktionsbara objekt som ska anpassas för din nya interaktion. På så sätt kan alla befintliga interaktionsbara objekt dra nytta av fördelarna med din nya interaktion i stället för endast de som du har skrivit om eller utökat.
XRControllers och indatabindning
De flesta interagerare binder inte direkt till indataåtgärder. De flesta härleds från XRBaseControllerInteractor
, som kräver en XRController
över interageraren i hierarkin. Bindningarna XRController
till indataåtgärderna och sprider sedan relevanta åtgärder (välj och så vidare) ned till alla anslutna interagerare.
Vissa interaktionsfaktorer kan dock behöva särskilda indatabindningar eller ytterligare indata som XRController
inte tillhandahålls. I dessa fall har interagerare möjlighet att binda direkt till sina egna unika indataåtgärder eller till och med använda andra icke-indatasystemkällor för interaktionslogik. XRI-basklasserna föredrar att lyssna på XRController
's bindningar, men dessa beteenden kan åsidosättas för att använda externa eller alternativa indatakällor.
Gränssnitt
XRI definierar grundläggande IXRInteractor
, IXRHoverInteractor
, IXRSelectInteractor
och IXRActivateInteractor
. MRTK definierar ytterligare gränssnitt för interagerare. Vissa exponerar ytterligare information om MRTK-specifika interaktioner, och andra är helt enkelt för kategorisering och identifiering. Dessa gränssnitt finns alla i Core-paketet , medan implementeringarna finns i andra paket, inklusive Indata.
Viktigt!
Även om dessa gränssnitt är användbara om du behöver filtrera efter en viss typ av interaktion rekommenderar vi att du inte hårdkodar dina interaktioner för att lyssna efter dessa gränssnitt specifikt. I varje situation ska du alltid prioritera den generiska XRI isSelected och isHovered, snarare än något interaktionsspecifikt gränssnitt.
Om det inte behövs bör du inte referera till de konkreta MRTK-implementeringarna av dessa gränssnitt i interaktionsbara objekt om det inte är absolut nödvändigt. I samtliga fall är det bättre att referera till gränssnitten. Om du uttryckligen refererar till de konkreta typerna begränsas dina interaktionsbara objekt till att endast fungera med de aktuella, befintliga typerna. Genom att bara referera till gränssnitten säkerställer du kompatibilitet med framtida implementeringar som kanske inte underklassar befintliga implementeringar.
IVariableSelectInteractor
Interagerare som implementerar det här gränssnittet kan utfärda variabel (dvs. analog) urval till interaktionsbara objekt. Variabeln välj belopp kan frågas med egenskapen SelectProgress
. MRTK-interagerare som implementerar det här gränssnittet innehåller MRTKRayInteractor
och GazePinchInteractor
. Bas-interaktionsbara objekt (standard-XRI-interaktionsbara objekt och MRTKBaseInteractable
) påverkas inte av variabelns urvalsmängd. StatefulInteractable
Lyssnar dock på det här värdet och beräknar dess Selectedness
baserat på max()
alla deltagande variabel- och icke-variabla interaktionsfaktorer.
IGazeInteractor
Interagerare som implementerar det här gränssnittet representerar användarens passiva blick, separat från alla manipulationer eller avsikter. MRTK-implementeringen är FuzzyGazeInteractor
, som ärver från XRI XRRayInteractor
och lägger till fuzzy cone-casting-logik. XRBaseInteractable
flaggar IsGazeHovered
när en IGazeInteractor
hovrar.
IGrabInteractor
Interagerare som implementerar det här gränssnittet representerar en fysisk interaktion nära fältet. attachTransform
Definieras som grepppunkten. MRTK-implementeringen är GrabInteractor
, som underklassar XRI:s XRDirectInteractor
.
IPokeInteractor
Interagerare som implementerar det här gränssnittet representerar en petande interaktion. Observera att detta inte nödvändigtvis innebär ett finger! Godtyckliga interaktionsfaktorer kan implementera det här gränssnittet och erbjuda petande interaktioner från icke-fingerkällor. I en av de få instanser där kontroll av interaktionsgränssnitt är en bra idé är interaktionsbara objekt som PressableButton
att lyssna efter s, specifikt, för IPokeInteractor
att driva volympress. Alla interagerare som implementerar IPokeInteractor
kommer att inducera 3D-tryck på knappar.
IPokeInteractor
exponerar PokeRadius
egenskapen, som definierar egenskaperna för poking-objektet. Poke anses vara centrerad på attachTransform
och sträcker sig utåt från attachTransform
av PokeRadius
. Interaktionsbara objekt som PressableButton
förskjuter sitt 3D-push-avstånd med den här radien, som kan drivas av användarens fysiska fingertjocklek när det gäller fingerbaserade tryckningar.
MRTK-implementeringen av det här gränssnittet är PokeInteractor
. I vårt mallprojekt ger vi också ett annat exempel på IPokeInteractor
som inte är fingerdrivet. PenInteractor
Det ger poke-interaktioner som är rotade på spetsen på en virtuell 3D-penna.
IRayInteractor
Interagerare som implementerar det här gränssnittet representerar en ray-baserad pekinteraktion. attachTransform
Representerar strålens träffplats på målobjektets yta under en markering.
MRTK-implementeringen av det här gränssnittet är MRTKRayInteractor
, ärver direkt från XRI XRRayInteractor
.
Kommentar
XRI XRRayInteractor
implementerar inte det här MRTK-gränssnittet.
ISpeechInteractor
Interagerare som implementerar det här gränssnittet representerar taldrivna interaktioner. MRTK-implementeringen är SpeechInteractor
.
MRTK SpeechInteractor
använder PhraseRecognitionSubsystem
och prenumererar internt på interaktionsbara registreringshändelser från XRI XRInteractionManager
. Interaktionsbara objekt behöver dock inte bry sig om vilket undersystem som utför talbearbetning. ISpeechInteractor
s genererar samma XRI-händelser (välj och så vidare) som andra interagerare gör.
IGazePinchInteractor
Det här gränssnittet är helt enkelt en specialisering av IVariableSelectInteractor
gränssnittet. Interagerare som implementerar det här gränssnittet är implicit interagerare med variabelval. IGazePinchInteractor
s uttryckligen representerar en indirekt riktad fjärrmanipulering. En separat blickbaserad interagerare styr interaktionens mål, och manipuleringen sker av en hand eller kontrollant. attachTransform
beter sig på samma sätt som IRayInteractor
's attachTransform
gör; den fäster mot träffpunkten på målet när ett val initieras.
När flera IGazePinchInteractor
deltar i en enda interaktion förskjuts deras attachTransform
s av deras förskjutning från medianpunkten mellan alla deltagande nyppunkter. Därför kan interaktionsbara objekt tolka dessa attachTransform
på samma sätt som de skulle göra för andra interaktioner med flera händer, till exempel attachTransforms
interaktioner från grab eller ray-interaktioner.
MRTK-implementeringen är GazePinchInteractor
.
IHandedInteractor
Vissa interagerare kan välja att implementera IHandedInteractor
gränssnitt för att uttryckligen ange att de är associerade med en viss hand på en användare. Vissa interagerare är inte associerade med handlighet och implementerar därför inte detta. De mest uppenbara exemplen skulle vara sådana som SpeechInteractor
eller FuzzyGazeInteractor
.
MRTK-interagerarna som implementerar det här gränssnittet är HandJointInteractor
, en generisk, abstrakt XRDirectInteractor
som drivs av en godtycklig handfog, GazePinchInteractor
, och MRTKRayInteractor
.
Interaktionsbara objekt använder för närvarande det här gränssnittet för att utlösa vissa effekter när de väljs som måste skiljas mellan en vänster eller höger hand. Det mest anmärkningsvärda exemplet på detta är pulseffekten i biblioteket för UX-komponenter.