Solvers – MRTK3
Lösare är komponenter som underlättar beräkningen av ett objekts position och orientering enligt en fördefinierad algoritm. Exempel: Placera ett objekt på ytan som användarens blickstråle korsar.
Solversystemet definierar deterministiskt en åtgärdsordning för dessa transformeringsberäkningar eftersom det inte finns något tillförlitligt sätt att ange uppdateringsordningen för komponenter i Unity.
Problemlösare erbjuder en rad olika beteenden för att koppla objekt till andra objekt eller system. Ett annat exempel skulle vara ett tagg-along-objekt som hovrar framför användaren baserat på kameran. En lösningslösare kan också kopplas till en kontrollant och ett objekt för att göra objekttaggen längs kontrollanten. Alla lösare kan vara säkert staplade – till exempel ett tag-along-beteende plus ytmagnetism plus momentum.
Så här använder du funktionen
Solversystemet består av tre kategorier av skript:
Solver
: Den abstrakta basklassen som alla lösare härleds från. Den tillhandahåller tillståndsspårning, utjämning av parametrar och implementering, automatisk systemintegrering av lösare och uppdateringsordning.SolverHandler
: Anger referensobjektspårningen mot (till exempel huvudkameratransformering, handstråle osv.), hanterar insamlingen av lösarkomponenter och kör uppdatering av dem i rätt ordning.
Den tredje kategorin är själva lösaren. Följande lösare tillhandahåller byggstenarna för grundläggande beteende:
Orbital
: Låser till en angiven position och förskjuts från det refererade objektet.ConstantViewSize
: Skalar för att bibehålla en konstant storlek i förhållande till vyn för det refererade objektet.RadialView
: Håller objektet inom en vykon som är gjuten av det refererade objektet.Follow
: Håller objektet inom en uppsättning användardefinierade gränser för det refererade objektet.InBetween
: Håller ett objekt mellan två spårade objekt.SurfaceMagnetism
: kastar strålar till ytor i världen och justerar objektet till den ytan.DirectionalIndicator
: Avgör positionen och orienteringen för ett objekt som en riktningsindikator. Från referenspunkten för SolverHandler Tracked Target kommer den här indikatorn att orientera sig mot den directionalTarget som tillhandahålls.Momentum
: Tillämpar acceleration/hastighet/friktion för att simulera momentum och springiness för ett objekt som flyttas av andra lösare/komponenter.HandConstraint
: Villkorsobjekt för att följa händer i en region som inte korsar GameObject med händerna. Användbart för handbegränsat interaktivt innehåll, till exempel menyer osv. Den här lösaren är avsedd att fungera medXRNode
.HandConstraintPalmUp
: Härleds från HandConstraint men innehåller logik för att testa om handflatan är riktad mot användaren före aktiveringen. Den här lösaren fungerar bara medXRNode
kontrollanter och fungerar precis som basklassen med andra kontrollanttyper.Overlap
: Överlappar det spårade objektet.
Om du vill använda Solver-systemet lägger du till en av komponenterna som anges ovan i en GameObject. Eftersom alla problemlösare kräver en SolverHandler
skapas en automatiskt av Unity.
Kommentar
Exempel på hur du använder Solvers-systemet finns i filen SolverExamples.scene .
Ändra spårningsreferens
Egenskapen Spårad måltyp för komponenten SolverHandler
definierar referenspunkten som alla lösare använder för att beräkna sina algoritmer. Till exempel resulterar en värdetyp av Head
med en enkel SurfaceMagnetism
komponent i en stråle från huvudet och i riktning mot användarens blick för att lösa vilken yta som träffas. Potentiella värden för egenskapen TrackedTargetType
är:
- *Huvud: Referenspunkt är transformering av huvudkameran
- ControllerRay: Referenspunkten är transformen
LinePointer
på en styrenhet (dvs. pekarens ursprung på en rörelsestyrenhet eller handstyrenhet) som pekar i linjestrålens riktning- Använd egenskapen
TrackedHandedness
för att välja inställningarna för handlighet (det vill: Vänster, Höger, Båda)
- Använd egenskapen
- HandJoint: Referenspunkt är omvandlingen av en specifik handfog
- Använd egenskapen
TrackedHandedness
för att välja inställningarna för handlighet (det vill: Vänster, Höger, Båda) - Använd egenskapen
TrackedHandJoint
för att fastställa den gemensamma transformering som ska användas
- Använd egenskapen
- CustomOverride: Referenspunkt från den tilldelade
TransformOverride
Kommentar
För både ControllerRay - och HandJoint-typerna försöker lösaren först tillhandahålla den vänstra kontrollanten/handtransformen och sedan höger om den förstnämnda inte är tillgänglig eller om inte TrackedHandedness
egenskapen anger något annat.
Viktigt!
De flesta lösningslösare använder den framåtriktade vektorn för det spårade transformeringsmålet som tillhandahålls av SolverHandler
. När du använder en handled spårad måltyp kan den främre vektorn i palmleden peka genom fingrarna och inte genom handflatan. Detta beror på vilken plattform som tillhandahåller gemensamma handdata. För indatasimulering och Windows Mixed Reality pekar uppvektorn upp genom handflatan (med andra ord är den gröna vektorn uppe, den blå vektorn är framåt).
Du kan lösa detta genom att uppdatera egenskapen Ytterligare rotation på SolverHandler
till <90, 0, 0>. Detta säkerställer att den framåtvektor som levereras till lösarna pekar genom handflatan och utåt bort från handen.
Du kan också använda kontrollantens ray-spårade måltyp för att få liknande beteende för att peka med händerna.
Så här kedjar du lösare
Det är möjligt att lägga till flera Solver
komponenter i samma GameObject och därmed länka sina algoritmer. Komponenterna SolverHandler
hanterar uppdatering av alla lösare på samma GameObject. Som standard anropen SolverHandler
GetComponents<Solver>()
på Start, som returnerar Solvers i den ordning de visas i inspektören.
Om egenskapen Uppdaterad länkad transformering anges till true instrueras dessutom att Solver
spara sin beräknade position, orientering och skala till en mellanliggande variabel som är tillgänglig för alla problemlösare (dvs GoalPosition
. ). När det är falskt Solver
uppdateras GameObjects transformering direkt. Genom att spara transformeringsegenskaperna på en mellanliggande plats kan andra problemlösare utföra sina beräkningar från och med variabeln mellanhand. Det beror på att Unity inte tillåter att uppdateringar av gameObject.transform staplas inom samma ram.
Kommentar
Utvecklare kan ändra körningsordningen för Solvers genom att ange SolverHandler.Solvers
egenskapen direkt.
Så här skapar du en ny lösning
Alla lösare måste ärva från den abstrakta basklassen, Solver
. De primära kraven för ett Solver-tillägg innebär att SolverUpdate
åsidosätta metoden. I den här metoden bör utvecklare uppdatera egenskaperna ärvda GoalPosition
, GoalRotation
och GoalScale
till önskade värden. Dessutom är det värdefullt att använda SolverHandler.TransformTarget
som referensram som konsumenten önskar.
Koden nedan ger ett exempel på en ny Solver-komponent med namnet InFront
som placerar det bifogade objektet 2 m framför SolverHandler.TransformTarget
. Konsumenten anger SolverHandler.TrackedTargetType
som Head
, då SolverHandler.TransformTarget
kommer att vara kameran transformeras, och därmed denna Solver kommer att placera den bifogade GameObject 2 m framför användarnas blick varje bildruta.
/// <summary>
/// InFront solver positions an object 2m in front of the tracked transform target
/// </summary>
public class InFront : Solver
{
...
public override void SolverUpdate()
{
if (SolverHandler != null && SolverHandler.TransformTarget != null)
{
var target = SolverHandler.TransformTarget;
GoalPosition = target.position + target.forward * 2.0f;
}
}
}
Implementeringsguider för lösare
Vanliga problemlösningsegenskaper
Varje Solver-komponent har en grundläggande uppsättning identiska egenskaper som styr kärnbeteendet för Solver.
Om utjämning är aktiverat uppdaterar lösaren gradvis omvandlingen av GameObject över tid till de beräknade värdena. Varje transformeringskomponents LerpTime-egenskap avgör hastigheten för den här ändringen. Ett högre MoveLerpTime-värde resulterar till exempel i långsammare ökningar i rörelse mellan bildrutor.
Om MaintainScale är aktiverat använder lösaren GameObjects lokala standardskala.
Orbital
Klassen Orbital
är en tag-along-komponent som beter sig som planeter i ett solsystem. Den här lösaren säkerställer att den anslutna GameObject kretsar runt den spårade transformen. Om den spårade måltypen SolverHandler
för är inställd på Head
, kommer GameObject därför att kretsa runt användarens huvud med en fast förskjutning tillämpad.
Utvecklare kan ändra den här fasta förskjutningen för att hålla menyer eller andra scenkomponenter på ögonnivå eller midjenivå osv. runt en användare. Detta görs genom att ändra egenskaperna Lokal förskjutning och Världsförskjutning . Egenskapen Orienteringstyp avgör rotationen som tillämpas på objektet om det ska behålla sin ursprungliga rotation eller alltid möta kameran eller ansiktet oavsett vilken transformering som driver dess position.
RadialVy
RadialView
är en annan tag-along-komponent som håller en viss del av en GameObject inom frustum för användarens vy.
Egenskaperna Minsta och högsta visningsgrader avgör hur mycket av en del av GameObject som alltid måste visas.
Egenskaperna Min och Max avstånd avgör hur långt GameObject ska hållas från användaren. Om du till exempel går mot GameObject med ett minsta avstånd på 1 m kommer GameObject att skjutas bort för att säkerställa att det aldrig är närmare än 1 m till användaren.
RadialView
I allmänhet används med Spårad måltyp inställd på Head
så att komponenten följer användarens blick. Den här komponenten kan dock fungera för att hållas i "vy" för alla spårade måltyper.
Följ
Klassen Follow
placerar ett element framför det spårade målet i förhållande till den lokala framåtaxeln. Elementet kan vara löst begränsat (även kallat "tag-along") så att det inte följer förrän det spårade målet flyttas bortom användardefinierade gränser.
Den fungerar på samma sätt som RadialView-lösaren, med ytterligare kontroller för att hantera maximala vågräta och lodräta visningsgrader och mekanismer för att ändra objektets orientering.
InBetween
Klassen InBetween
behåller det kopplade GameObject mellan två transformeringar. GameObjects egen SolverHandler
spårade måltyp och komponentens InBetween
second tracked target type-egenskap definierar dessa två transformeringsslutpunkter. I allmänhet anges båda typerna till CustomOverride
och resultatet SolverHandler.TransformOverride
och InBetween.SecondTransformOverride
värdena anges till de två spårade slutpunkterna.
Komponenten InBetween
skapar en annan SolverHandler
komponent vid körning baserat på egenskaperna Second Tracked Target Type och Second Transform Override .
Längs linjen mellan två transformeringar PartwayOffset
definierar var objektet ska placeras med 0,5 som halvvägs, 1,0 vid den första transformen och 0,0 vid den andra transformen.
SurfaceMagnetism
Verken SurfaceMagnetism
genom att utföra en raycast mot en uppsättning LayerMask av ytor och placera GameObject vid den kontaktpunkten.
Surface Normal Offset placerar GameObject ett angivet avstånd i meter från ytan i riktning mot det normala vid träffpunkten på ytan.
Omvänt kommer Surface Ray Offset att placera GameObject ett fast avstånd i meter bort från ytan men i motsatt riktning mot raycast utförs. Således, om raycasten är användarens blick, kommer GameObject att röra sig närmare längs linjen från träffpunkten på ytan till kameran.
Orienteringsläget avgör vilken typ av rotation som ska tillämpas i förhållande till det normala på ytan.
- Ingen – Ingen rotation har tillämpats
- TrackedTarget – Objektet kommer att möta den spårade transformering som driver raycasten
- SurfaceNormal – Objektet justeras baserat på det normala vid träffpunkten på ytan
- Blandat – Objektet justeras baserat på det normala vid träffpunkten på ytan OCH baserat på den spårade transformeringen.
Om du vill tvinga den associerade GameObject att förbli lodrät i något annat läge än Inget aktiverar du Håll orienteringen lodrät.
Kommentar
Använd egenskapen Orienteringsblandning för att styra balansen mellan rotationsfaktorer när orienteringsläget är inställt på Blandat. Värdet 0.0 kommer att ha orientering helt och hållet drivet av TrackedTarget-läget , och värdet 1.0 har orientering som helt drivs av SurfaceNormal.
Överlappning
Overlap
är en enkel lösning som håller objektets transformering vid samma position och rotation som transformeringsmåletSolverHandler's
.
Avgöra vilka ytor som kan träffas
När du lägger till en SurfaceMagnetism
komponent i en GameObject är det viktigt att tänka på lagret av GameObject och dess barn, om någon har kolliderare. Komponenten fungerar genom att utföra olika raycasts för att avgöra vilken yta att "magnet" sig mot. Anta att lösaren GameObject har en kolliderare på ett av de lager som anges i MagneticSurfaces
egenskapen SurfaceMagnetism
. I så fall kommer raycasten sannolikt att träffa sig själv, vilket resulterar i att GameObject ansluter till sin egen kolliderarpunkt. Det här udda beteendet kan undvikas genom att ställa in huvudnivån GameObject och alla underordnade till Ignorera Ray-gjutna lager eller ändra LayerMask-matrisen MagneticSurfaces
på rätt sätt.
Omvänt kolliderar inte en SurfaceMagnetism
GameObject med ytor på ett lager som inte anges i egenskapen MagneticSurfaces
. Vi rekommenderar att du placerar alla önskade ytor på ett dedikerat lager (dvs . Ytor) och ställer in MagneticSurfaces
egenskapen på just det här lagret. Om du använder standard eller så kan allt resultera i att gränssnittskomponenter eller markörer bidrar till lösaren.
Slutligen ignoreras ytor längre än egenskapsinställningen MaxRaycastDistance
SurfaceMagnetism
av raycasts.
DirectionalIndicator
Klassen DirectionalIndicator
är en tagg-along-komponent som orienterar sig mot riktningen för önskad punkt i rymden. Den används oftast när den spårade måltypen för är inställd på SolverHandler
Head
. På det här sättet instruerar en UX-komponent med DirectionalIndicator
lösaren en användare att titta på önskad plats i utrymmet. Den här punkten bestäms av egenskapen Directional Target .
Om riktningsmålet kan visas av användaren eller vilken referensram som anges i SolverHandler
, inaktiverar den här lösaren alla Renderer
komponenter under den. Om den inte kan visas aktiveras allt på indikatorn.
Indikatorns storlek krymper desto närmare är användaren att samla in riktningsmålet i sin FOV.
Minsta indikatorskala – minsta skala för indikatorobjektet
Maximal indikatorskala – Den maximala skalan för indikatorobjektet
Synlighetsskalningsfaktor – Multiplikator för att öka eller minska FOV som avgör om riktningsmålpunkten kan visas eller inte
Visa förskjutning – Från referensramens synvinkel (det vill säga kamera möjligen) och i indikatorriktningen definierar den här egenskapen hur långt objektet är från mitten av visningsområdet.
Exempelscen för riktningsindikator (Assets/MRTK/Examples/Demos/Solvers/Scenes/DirectionalIndicatorSolverExample.unity)
Handmeny med HandConstraint och HandConstraintPalmUp
Beteendet HandConstraint
ger en lösning som begränsar det spårade objektet till en region som är säker för handbegränsat innehåll (till exempel handgränssnitt, menyer osv.) Säkra regioner betraktas som områden som inte korsar handen. En härledd klass med HandConstraint
anropad HandConstraintPalmUp
ingår också för att demonstrera ett vanligt beteende för att aktivera det lösningsspårade objektet när handflatan är riktad mot användaren.
I handmenydokumentationen finns exempel på hur du använder handbegränsningslösaren för att skapa handmenyer.