Problemlösningsöversikt
Solvers är komponenter som underlättar beräkning av ett objekts positionsorientering & enligt en fördefinierad algoritm. Ett exempel kan vara att placera ett objekt på ytan som användarens blickstråle för närvarande träffar.
Dessutom definierar Solver-systemet 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.
Lösningslösare erbjuder en rad olika beteenden för att koppla objekt till andra objekt eller system. Ett annat exempel är ett tag-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 objektet tagg längs kontrollanten. Alla lösare kan staplas på ett säkert sätt, till exempel ett tag-along-beteende + ytmagnetism + momentum.
Så här använder du en lösning
Solversystemet består av tre kategorier av skript:
Solver
: Den grundläggande abstrakta klassen som alla lösare härleds från. Den tillhandahåller tillståndsspårning, utjämning av parametrar och implementering, automatisk problemlösningssystemintegrering och uppdateringsordning.SolverHandler
: Anger referensobjektet som ska spåras mot (t.ex. huvudkameratransformering, handstråle osv.), hanterar insamling av lösarkomponenter och kör uppdatering av dem i rätt ordning.
Den tredje kategorin är själva lösaren. Följande lösningslö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 upprätthålla en konstant storlek i förhållande till vyn för det refererade objektet.RadialView
: Håller objektet inom en vykon 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 mot 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 levereras.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
: Begränsar objektet så att det följer händerna 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 med IMixedRealityHand men fungerar även med IMixedRealityController.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 med IMixedRealityHand-styrenheter , med andra kontrollanttyper som den här lösaren fungerar precis som dess basklass.
För att använda Solver-systemet lägger du helt enkelt till en av komponenterna som anges ovan i ett GameObject. Eftersom alla solvers kräver en SolverHandler
skapas en automatiskt av Unity.
Anteckning
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 raycast 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 omvandlingen 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 handenhetsinställningen (t.ex. 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 handenhetsinställningen (t.ex. 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
Anteckning
För både ControllerRay - och HandJoint-typer försöker lösaren att först tillhandahålla den vänstra kontrollanten/handtransformering och sedan höger om den förstnämnda inte är tillgänglig eller om inte TrackedHandedness
egenskapen anger något annat.
Exempel på olika egenskaper som är associerade med varje TrackedTargetType
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 framåtriktade 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 är det uppvektorn som pekar upp genom handflatan (dvs. den gröna vektorn är 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åtriktade vektorn som levereras till lösare pekar genom handflatan och utåt bort från handen.
Du kan också använda kontrollanten Ray-spårad 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 som de visas i inspektören.
Om du anger egenskapen Uppdaterad länkad transformering till true instrueras dessutom att Solver
spara dess beräknade position, orientering, & skala till en mellanliggande variabel som är tillgänglig för alla solvers (dvs GoalPosition
. ). När det är falskt Solver
uppdateras GameObjects transformering direkt. Genom att spara transformeringsegenskaperna på en mellanliggande plats kan andra solvers utföra sina beräkningar från variabeln mellanhand. Det beror på att Unity inte tillåter att uppdateringar av gameObject.transform staplas inom samma ram.
Anteckning
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 omfattar att SolverUpdate
åsidosätta metoden. I den här metoden bör utvecklare uppdatera de ärvda GoalPosition
GoalRotation
egenskaperna och GoalScale
till önskade värden. Dessutom är det i allmänhet värdefullt att utnyttja SolverHandler.TransformTarget
som den referensram som konsumenten önskar.
Koden nedan ger ett exempel på en ny Solver-komponent med namnet InFront
som placerar det anslutna objektet 2 m framför SolverHandler.TransformTarget
. SolverHandler.TrackedTargetType
Om anges av konsumenten som Head
, då SolverHandler.TransformTarget
kommer att vara kameran transformera och därmed denna Solver kommer att placera den anslutna GameObject 2m 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 lösningsegenskaper
Varje Solverkomponent har en kärnuppsä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. Hastigheten för den här ändringen bestäms av varje transformeringskomponents LerpTime-egenskap . Ett högre MoveLerpTime-värde resulterar till exempel i långsammare steg i rörelse mellan bildrutor.
Om MaintainScale är aktiverat använder lösaren GameObjects lokala standardskala.
Vanliga egenskaper som ärvs av alla Solver-komponenter
Orbital
Klassen Orbital
är en tag-along-komponent som beter sig som planeter i ett solsystem. Denna solver säkerställer att den anslutna GameObject kretsar runt den spårade transformen. Om den spårade måltypenSolverHandler
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 denna fasta förskjutning för att hålla menyer eller andra scenkomponenter på ögonnivå eller i midjenivå etc. 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 vända sig mot kameran eller ansiktet oavsett vilken transformering som driver dess position osv.
Orbital-exempel
Radiell vy
RadialView
är en annan tagg-along-komponent som håller en viss del av en GameObject inom frustum i användarens vy.
Egenskaperna Minsta & maximala visningsgrader avgör hur stor del av GameObject som alltid måste visas.
Egenskaperna minsta & maxavstå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 skjuter du bort GameObject för att säkerställa att den aldrig är närmare än 1 m till användaren.
RadialView
I allmänhet används tillsammans med Spårad måltyp inställd Head
på så att komponenten följer användarens blick. Den här komponenten kan dock fungera för att hållas i "vy" av alla spårade måltyper.
RadialView-exempel
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 (t.ex. tagg-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 lodräta & visningsgrader och mekanismer för att ändra objektets orientering .
Följ egenskaper
Följ exempelscen (Assets/MRTK/Examples/Demos/Solvers/Scenes/FollowSolverExample.unity)
Emellan
Klassen InBetween
behåller det kopplade GameObject mellan två transformeringar. Dessa två transformeringsslutpunkter definieras av GameObjects egen SolverHandler
spårade måltyp och komponentens InBetween
second tracked target type-egenskap . I allmänhet anges båda typerna till CustomOverride
och de resulterande SolverHandler.TransformOverride
värdena och InBetween.SecondTransformOverride
värdena anges till de två spårade slutpunkterna.
Vid körning skapar komponenten InBetween
en annan SolverHandler
komponent baserat på egenskaperna Second Tracked Target Type (Second Tracked Target Type ) och Second Transform Override (Åsidosättning av andra transformering ).
Definierar PartwayOffset
var längs linjen mellan två transformeringar objektet ska placeras med 0,5 som halvvägs, 1,0 vid den första transformen och 0,0 vid den andra transformen.
Exempel på hur du använder InBetween-lösaren för att behålla objektet mellan två transformeringar
SurfaceMagnetism
Verken SurfaceMagnetism
genom att utföra en raycast mot en angiven 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 från ytan, men i motsatt riktning mot den raycast som utförs. Så 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 tillämpas
- TrackedTarget – Objektet kommer att möta den spårade transformen 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 transformen.
Om du vill tvinga det associerade GameObject att vara lodrätt i något annat läge än Inget aktiverar du Håll orienteringen lodrät.
Anteckning
Använd egenskapen Orienteringsblandning för att styra balansen mellan rotationsfaktorer när Orienteringsläge ä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 kommer att ha orientering som helt drivs av SurfaceNormal.
Fastställa vilka ytor som kan träffas
När du lägger till en SurfaceMagnetism
komponent i ett GameObject är det viktigt att tänka på lagret i GameObject och dess underordnade objekt, om det finns några som har kolliderare. Komponenten fungerar genom att utföra olika typer av raycasts för att avgöra vilken yta man ska "magnet" sig mot. Om lösaren GameObject har en collider på ett av lagren som anges i MagneticSurfaces
egenskapen för SurfaceMagnetism
kommer raycasten troligen att träffa sig själv, vilket resulterar i att GameObject kopplas till sin egen collider-punkt. Det här udda beteendet kan undvikas genom att ange huvudnivån GameObject och alla underordnade till Ignore Raycast-lagret eller genom att ändra LayerMask-matrisen MagneticSurfaces
på rätt sätt.
Däremot kolliderar inte ett SurfaceMagnetism
GameObject med ytor på ett lager som inte anges i MagneticSurfaces
egenskapen. Vi rekommenderar vanligtvis 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 kommer ytor längre än egenskapsinställningen MaxRaycastDistance
att ignoreras av SurfaceMagnetism
raycasts.
DirectionalIndicator
Klassen DirectionalIndicator
är en taggningskomponent som orienterar sig efter riktningen för en önskad punkt i rymden.
Används oftast när den spårade måltypen för SolverHandler
är inställd på Head
. På så sätt uppmanar en UX-komponent med DirectionalIndicator
lösaren en användare att titta på önskad punkt i utrymmet.
Önskad punkt i utrymmet bestäms via egenskapen Riktningsmål .
Om användaren kan se riktningsmålet, eller vilken referensram som anges i SolverHandler
, inaktiverar den här lösaren alla Renderer
komponenter under den. Om den inte visas aktiveras allt på indikatorn.
Indikatorns storlek krymper desto närmare är användaren att fånga 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 den FOV som avgör om riktningsmålets punkt är synlig eller inte
Visa förskjutning – Från referensramens synvinkel (t.ex. kamera möjligen) definierar den här egenskapen hur långt i indikatorriktningen objektet ska vara från mitten av visningsområdet.
Egenskaper för riktningsindikator
Exempelscen för riktningsindikator (Assets/MRTK/Examples/Demos/Solvers/Scenes/DirectionalIndicatorSolverExample.unity)
Handmeny med HandConstraint och HandConstraintPalmUp
Beteendet HandConstraint
ger en lösare 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.). Valv regioner betraktas som områden som inte korsas med handen. En härledd klass med HandConstraint
anropas HandConstraintPalmUp
ingår också för att demonstrera ett vanligt beteende för att aktivera det lösenspårade objektet när handflatan är riktad mot användaren.
På sidan Handmeny finns exempel på hur du använder handbegränsningslösaren för att skapa handmenyer.