Delen via


Overzicht van Oplosser — MRTK2

Hoofd oplosser

Oplossers zijn onderdelen die de methode voor het berekenen van de positie & oriëntatie van een object vergemakkelijken volgens een vooraf gedefinieerd algoritme. Een voorbeeld is het plaatsen van een object op het oppervlak dat de raycast van de gebruiker momenteel raakt.

Bovendien definieert het Oplosser-systeem deterministisch een volgorde van bewerkingen voor deze transformatieberekeningen, omdat er geen betrouwbare manier is om de updatevolgorde voor onderdelen aan Unity op te geven.

Oplossers bieden een reeks gedragingen om objecten aan andere objecten of systemen te koppelen. Een ander voorbeeld is een tag-along-object dat voor de gebruiker wordt geplaatst (op basis van de camera). Een oplosser kan ook worden gekoppeld aan een controller en een object om het object te taggen langs de controller. Alle oplossers kunnen veilig worden gestapeld, bijvoorbeeld een tag-along gedrag + oppervlakte magnetisme + momentum.

Een oplosser gebruiken

Het Oplosser-systeem bestaat uit drie categorieën scripts:

  • Solver: De abstracte basisklasse waaruit alle oplossers zijn afgeleid. Het biedt statustracering, vloeiende parameters en implementatie, automatische oplossersysteemintegratie en updatevolgorde.
  • SolverHandler: Hiermee stelt u het referentieobject in dat moet worden bijgehouden (bijvoorbeeld de hoofdcameratransformatie, handstraal, enzovoort), wordt het verzamelen van oplosseronderdelen afgehandeld en worden deze in de juiste volgorde bijgewerkt.

De derde categorie is de oplosser zelf. De volgende oplossers bieden de bouwstenen voor basisgedrag:

  • Orbital: Vergrendelt naar een opgegeven positie en offset van het object waarnaar wordt verwezen.
  • ConstantViewSize: schaalt om een constante grootte te behouden ten opzichte van de weergave van het object waarnaar wordt verwezen.
  • RadialView: Houdt het object binnen een weergavekegel die wordt gegoten door het object waarnaar wordt verwezen.
  • Follow: houdt het object binnen een set door de gebruiker gedefinieerde grenzen van het object waarnaar wordt verwezen.
  • InBetween: houdt een object tussen twee bijgehouden objecten.
  • SurfaceMagnetism: werpt stralen naar oppervlakken in de wereld en lijn het object uit op dat oppervlak.
  • DirectionalIndicator: Bepaalt de positie en richting van een object als een richtingsindicator. Vanaf het referentiepunt van het OplosserHandler Tracked Target, zal deze indicator zich richten op de opgegeven DirectionalTarget.
  • Momentum: Past versnelling/snelheid/wrijving toe om momentum en springiness te simuleren voor een object dat wordt verplaatst door andere oplossers/onderdelen.
  • HandConstraint: Hiermee wordt het object beperkt om handen te volgen in een gebied dat het GameObject niet doorkruist met de handen. Handig voor interactieve inhoud met beperkte hand, zoals menu's, enzovoort. Deze oplosser is bedoeld om te werken met IMixedRealityHand maar werkt ook met IMixedRealityController.
  • HandConstraintPalmUp: is afgeleid van HandConstraint, maar bevat logica om te testen of de palm naar de gebruiker gericht is vóór activering. Deze oplosser werkt alleen met IMixedRealityHand-controllers , met andere controllertypen gedraagt deze oplosser zich net als zijn basisklasse.

Als u het Oplosser-systeem wilt gebruiken, voegt u gewoon een van de hierboven genoemde onderdelen toe aan een GameObject. Omdat alle Oplossers een SolverHandlervereisen, wordt er automatisch een gemaakt door Unity.

Notitie

Voorbeelden van het gebruik van het oplossersysteem vindt u in het bestand OplosserExamples.scene .

Traceringsreferentie wijzigen

De eigenschap Bijgehouden doeltype van het SolverHandler onderdeel definieert het referentiepunt dat alle oplossers gebruiken om hun algoritmen te berekenen. Een waardetype van Head met een eenvoudig SurfaceMagnetism onderdeel resulteert bijvoorbeeld in een raycast vanaf het hoofd en in de richting van de blik van de gebruiker voor het oplossen van welk oppervlak wordt geraakt. Mogelijke waarden voor de TrackedTargetType eigenschap zijn:

  • Hoofd : Referentiepunt is de transformatie van de hoofdcamera
  • ControllerRay: Het referentiepunt is de LinePointer transformatie op een controller (dat wil zeggen de oorsprong van de aanwijzer op een bewegingscontroller of handcontroller) die in de richting van de lijnstraal wijst
    • Gebruik de TrackedHandedness eigenschap om de voorkeur voor het gebruik van de hand te selecteren (bijvoorbeeld Links, Rechts, Beide)
  • HandJoint: Referentiepunt is de transformatie van een specifieke handverbinding
    • Gebruik de TrackedHandedness eigenschap om de voorkeur voor het gebruik van de hand te selecteren (bijvoorbeeld Links, Rechts, Beide)
    • Gebruik de TrackedHandJoint eigenschap om de te gebruiken gezamenlijke transformatie te bepalen
  • CustomOverride: referentiepunt van de toegewezen TransformOverride

Notitie

Voor zowel het type ControllerRay als het Type HandJoint probeert de handler eerst de linkercontroller/handtransformatie op te geven en vervolgens de rechter als de eerste niet beschikbaar is of tenzij de TrackedHandedness eigenschap anders aangeeft.

Oplosser Bijgehouden objectVoorbeeld van verschillende eigenschappen die zijn gekoppeld aan elk TrackedTargetType

Belangrijk

De meeste oplossers gebruiken de voorwaartse vector van het doel voor bijgehouden transformatie dat wordt geleverd door de SolverHandler. Bij gebruik van een handgewricht getraceerd doeltype, kan de voorwaartse vector van de palmverbinding door de vingers wijzen en niet door de palm. Dit is afhankelijk van het platform dat de hand gezamenlijke gegevens levert. Voor invoersimulatie en Windows Mixed Reality is het de omhoogvector die omhoog wijst door de palm (dat wil zeggen groene vector is omhoog, blauwe vector is vooruit).

Voorwaartse vector omhoog

U kunt dit oplossen door de eigenschap Extra rotatie op de SolverHandler bij te werken naar <90, 0, 0>. Dit zorgt ervoor dat de voorwaartse vector die aan oplossers wordt geleverd, door de palm wijst en weg van de hand naar buiten wijst.

Extra draaiing

U kunt ook het doeltype Controller Ray tracked gebruiken om vergelijkbaar gedrag te krijgen voor het aanwijzen met handen.

Hoe oplossers te ketenen

Het is mogelijk om meerdere Solver onderdelen toe te voegen aan hetzelfde GameObject, waardoor hun algoritmen worden gekoppeld. De SolverHandler onderdelen verwerken het bijwerken van alle oplossers op hetzelfde GameObject. Standaard worden de aanroepen GetComponents<Solver>() in Start SolverHandler geretourneerd, die de Oplossers retourneren in de volgorde waarin ze in de inspector worden weergegeven.

Bovendien geeft het instellen van de eigenschap Bijgewerkte gekoppelde transformatie op true de opdracht Solver om de berekende positie, stand & schaal op te slaan naar een tussenliggende variabele die toegankelijk is voor alle Oplossers (d.w.z GoalPosition. ). Wanneer onwaar, wordt de Solver transformatie van het GameObject rechtstreeks bijgewerkt. Door de transformatie-eigenschappen op te slaan op een tussenliggende locatie, kunnen andere Oplossers hun berekeningen uitvoeren vanaf de tussenliggende variabele. Dit komt doordat Unity niet toestaat dat updates voor gameObject.transform binnen hetzelfde frame worden gestapeld.

Notitie

Ontwikkelaars kunnen de uitvoeringsvolgorde van Oplossers wijzigen door de eigenschap rechtstreeks in te SolverHandler.Solvers stellen.

Een nieuwe oplosser maken

Alle oplossers moeten overnemen van de abstracte basisklasse, Solver. De primaire vereisten van een Oplosser-extensie zijn het overschrijven van de SolverUpdate methode. Bij deze methode moeten ontwikkelaars de overgenomen GoalPositioneigenschappen en GoalRotationGoalScale bijwerken naar de gewenste waarden. Bovendien is het over het algemeen waardevol om te gebruiken SolverHandler.TransformTarget als referentiekader dat door de consument wordt gewenst.

De onderstaande code geeft een voorbeeld van een nieuw oplosser-onderdeel met de naam InFront dat het gekoppelde object 2m voor de SolverHandler.TransformTargetplaatst. Als de SolverHandler.TrackedTargetType is ingesteld door de consument als Head, dan zal de SolverHandler.TransformTarget de camera transformatie en dus zal deze Oplosser de gekoppelde GameObject 2m voor de blik van de gebruikers elk frame plaatsen.

/// <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;
        }
    }
}

Implementatiehandleidingen voor Oplosser

Algemene eigenschappen van oplosser

Elk Oplosser-onderdeel heeft een kernset met identieke eigenschappen die het kerngedrag van Oplosser bepalen.

Als Vloeiend maken is ingeschakeld, wordt de transformatie van het GameObject geleidelijk bijgewerkt naar de berekende waarden. De snelheid van deze wijziging wordt bepaald door de eigenschap LerpTime van elk transformatieonderdeel. Een hogere MoveLerpTime-waarde resulteert bijvoorbeeld in tragere stappen in de verplaatsing tussen frames.

Als MaintainScale is ingeschakeld, gebruikt de Oplosser de standaard lokale schaal van het GameObject.

Eigenschappen van Core Oplosser
Algemene eigenschappen die worden overgenomen door alle Oplosser-onderdelen

Orbital

De Orbital klasse is een tag-along-component die zich gedraagt als planeten in een zonnestelsel. Deze Oplosser zorgt ervoor dat de gekoppelde GameObject rond de bijgehouden transformatie draait. Dus als het bijgehouden doeltype van de SolverHandler is ingesteld op Head, zal het GameObject rond het hoofd van de gebruiker draaien met een vaste verschuiving toegepast.

Ontwikkelaars kunnen deze vaste verschuiving aanpassen om menu's of andere scèneonderdelen op oogniveau of op tailleniveau, enzovoort, rond een gebruiker te houden. Dit wordt gedaan door de eigenschappen Local Offset en World Offset te wijzigen. De eigenschap Type afdrukstand bepaalt de draaiing die op het object wordt toegepast als het de oorspronkelijke draaiing moet behouden of altijd de camera moet onder ogen zien of elke transformatie moet zien die de positie bepaalt, enzovoort.

Voorbeeld van orbitaal
Voorbeeld van orbitaal

Radiaalweergave

De RadialView is een ander tag-along-onderdeel dat een bepaald gedeelte van een GameObject binnen het frustum van de weergave van de gebruiker houdt.

De eigenschappen Min & Max View Degrees bepalen hoe groot een deel van het GameObject altijd in beeld moet zijn.

De eigenschappen Min & Max Distance bepalen hoe ver het GameObject van de gebruiker moet worden bewaard. Als u bijvoorbeeld naar het GameObject loopt met een minimale afstand van 1m, wordt het GameObject weggeduwd om ervoor te zorgen dat het zich nooit dichter dan 1 meter bij de gebruiker bevindt.

Over het algemeen wordt de RadialView gebruikt in combinatie met Bijgehouden doeltype ingesteld op Head , zodat het onderdeel de blik van de gebruiker volgt. Dit onderdeel kan echter functioneren om in 'weergave' te worden gehouden van elk bijgehouden doeltype.

RadialView-voorbeeld
RadialView-voorbeeld

Volgen

De Follow klasse plaatst een element vóór de van het bijgehouden doel ten opzichte van de lokale voorwaartse as. Het element kan losjes worden beperkt (of tag-along), zodat het niet volgt totdat het bijgehouden doel de door de gebruiker gedefinieerde grenzen overschrijdt.

Het werkt op dezelfde manier als de RadialView-oplosser, met extra besturingselementen voor het beheren van maximale horizontale & verticale weergavegraden en mechanismen om de afdrukstand van het object te wijzigen.

Eigenschappen volgen
Eigenschappen volgen

Voorbeeldscène volgen
Voorbeeldscène volgen (Assets/MRTK/Examples/Demos/Solvers/Scenes/FollowSolverExample.unity)

Inbetween

De InBetween klasse houdt het gekoppelde GameObject tussen twee transformaties. Deze twee transformatie-eindpunten worden gedefinieerd door het eigen SolverHandlerBijgehouden doeltype van het GameObject en de eigenschap Second Tracked Target Type van het InBetween onderdeel. Over het algemeen worden beide typen ingesteld op CustomOverride en de resulterende SolverHandler.TransformOverride waarden en InBetween.SecondTransformOverride ingesteld op de twee bijgehouden eindpunten.

Tijdens runtime maakt het InBetween onderdeel een ander SolverHandler onderdeel op basis van de eigenschappen Second Tracked Target Type en Second Transform Override .

De PartwayOffset definieert waar langs de lijn tussen twee transformaties het object moet worden geplaatst met 0,5 als halverwege, 1,0 bij de eerste transformatie en 0,0 bij de tweede transformatie.

Voorbeeld van InBetween
Voorbeeld van het gebruik van InBetween Oplosser om het object tussen twee transformaties te houden

SurfaceMagnetism

Het SurfaceMagnetism werkt door een raycast uit te voeren op een set LayerMask van oppervlakken en het GameObject op dat contactpunt te plaatsen.

De Surface Normal Offset plaatst het GameObject een ingestelde afstand in meters van het oppervlak in de richting van de normale op het raakpunt op het oppervlak.

Omgekeerd plaatst de Surface Ray Offset het GameObject een ingestelde afstand in meters van het oppervlak, maar in de tegenovergestelde richting van de uitgevoerde raycast. Dus als de raycast de blik van de gebruiker is, zal het GameObject dichter langs de lijn van het trefferpunt op het oppervlak naar de camera gaan.

De stand bepaalt het type draaiing dat moet worden toegepast ten opzichte van het normale oppervlak.

  • Geen - Geen draaiing toegepast
  • TrackedTarget - Object wordt geconfronteerd met de bijgehouden transformatie die de raycast aansturen
  • SurfaceNormal - Object wordt uitgelijnd op basis van normaal bij het trefferpunt op het oppervlak
  • Gemengd - Object wordt uitgelijnd op basis van normaal op het trefpunt op het oppervlak EN op basis van de richting van de bijgehouden transformatie.

Als u wilt afdwingen dat het gekoppelde GameObject verticaal blijft in een andere modus dan Geen, schakelt u Stand verticaal houden in.

Notitie

Gebruik de eigenschap Afdrukstand overvloeien om de balans tussen rotatiefactoren te bepalen wanneer de afdrukstand is ingesteld op Overvloeien. Een waarde van 0,0 wordt volledig aangestuurd door de TrackedTarget-modus en de waarde 1.0 heeft de richting volledig aangestuurd door SurfaceNormal.

SurfaceMagnetism-voorbeeld

Bepalen welke oppervlakken kunnen worden geraakt

Wanneer u een SurfaceMagnetism onderdeel aan een GameObject toevoegt, is het belangrijk om rekening te houden met de laag van het GameObject en de onderliggende elementen, als er bots zijn. Het onderdeel werkt door verschillende soorten raycasts uit te voeren om te bepalen tegen welk oppervlak "magneet" moet worden gebruikt. Als de oplosser GameObject een collider heeft op een van de lagen die worden vermeld in de MagneticSurfaces eigenschap van SurfaceMagnetism, zal de raycast waarschijnlijk zichzelf raken, waardoor het GameObject wordt gekoppeld aan een eigen colliderpunt. Dit vreemde gedrag kan worden vermeden door het hoofd-GameObject en alle onderliggende elementen in te stellen op de raycast-laag negeren of door de matrix LayerMask op de MagneticSurfaces juiste manier te wijzigen.

Omgekeerd zal een SurfaceMagnetism GameObject niet botsen met oppervlakken op een laag die niet wordt vermeld in de MagneticSurfaces eigenschap. Het wordt over het algemeen aanbevolen om alle gewenste oppervlakken op een toegewezen laag ( surfaces) te plaatsen en de MagneticSurfaces eigenschap alleen op deze laag in te stellen. Het gebruik van standaard of alles kan ertoe leiden dat UI-onderdelen of cursors bijdragen aan de oplosser.

Ten slotte worden oppervlakken verder dan de instelling van de MaxRaycastDistance eigenschap genegeerd door de SurfaceMagnetism raycasts.

DirectionalIndicator

De DirectionalIndicator klasse is een tag-along-onderdeel dat zich oriënteert naar de richting van een gewenst punt in de ruimte.

Wordt meestal gebruikt wanneer het bijgehouden doeltype van de SolverHandler is ingesteld op Head. Op deze manier stuurt een UX-onderdeel met de DirectionalIndicator oplosser een gebruiker naar het gewenste punt in de ruimte te kijken.

Het gewenste punt in de ruimte wordt bepaald via de eigenschap Directional Target .

Als het richtdoel zichtbaar is voor de gebruiker of een referentiekader is ingesteld in de SolverHandler, schakelt deze oplosser alle Renderer onderliggende onderdelen uit. Als dit niet zichtbaar is, wordt alles ingeschakeld op de indicator.

De grootte van de indicator wordt kleiner naar hoe dichter de gebruiker bij het vastleggen van het directionele doel in hun FOV is.

  • Minimumindicatorschaal : de minimale schaal voor het indicatorobject

  • Maximale indicatorschaal : de maximale schaal voor het indicatorobject

  • Zichtbaarheidsschaalfactor - Vermenigvuldiger om de FOV te verhogen of te verlagen die bepaalt of het gerichte doelpunt zichtbaar is of niet

  • Verschuiving van weergave: vanuit het perspectief van het referentiekader (bijvoorbeeld camera mogelijk) bepaalt deze eigenschap hoe ver in de richting van de indicator het object zich vanaf het midden van de viewport moet bevinden.

Eigenschappen van richtingsindicator
Eigenschappen van richtingsindicator

Voorbeeldscène voor directionele indicator
Voorbeeldscène voor directionele indicator (Assets/MRTK/Examples/Demos/Oplossers/Scènes/DirectionalIndicatorSolverExample.unity)

Handmenu met HandConstraint en HandConstraintPalmUp

Handmenu UX-voorbeeld

Het HandConstraint gedrag biedt een oplosser die het bijgehouden object beperkt tot een regio die veilig is voor beperkte inhoud met de hand (zoals de gebruikersinterface van de hand, menu's, enzovoort). Veilige regio's worden beschouwd als gebieden die niet met de hand snijden. Een afgeleide klasse van HandConstraint aangeroepen HandConstraintPalmUp is ook opgenomen om een algemeen gedrag aan te tonen van het activeren van het oplosser bijgehouden object wanneer de palm naar de gebruiker gericht is.

Zie de pagina Handmenu voor de voorbeelden van het gebruik van Handbeperking oplosser om handmenu's te maken.

Zie ook