Dela via


Handmeny – MRTK3

Handmeny

Med handmenyer kan användare ta fram handanslutet användargränssnitt för funktioner som används ofta. Det här är vanligtvis små knappgrupper som erbjuder snabba åtgärder. Men ibland ges mer komplexa layouter för att visa information eller inställningar till användaren som en handmeny, ofta med alternativet att "riva bort" menyn från handen och förankra den i världen.

Menyn Hand innehåller alternativen "Kräv platt hand" och "Använd blickaktivering" för att förhindra falsk aktivering när du interagerar med andra objekt. Vi rekommenderar att du använder dessa alternativ för att förhindra oönskad aktivering.

Exempelscen och Prefabs

Om du använder mallprojektet HandMenuExamples.unity visar flera vanliga konfigurationer för handmenyer, som alla använder skriptet HandConstraintPalmUp .

Exempelscen för handmeny

HandMenuLarge

Den här prefab demonstrerar exemplet på ett stort eller komplext användargränssnitt som kräver längre interaktionstid. För den här typen av användargränssnitt rekommenderar vi att du låser menyn till hands för att förbättra användbarheten och undvika armtrötthet. Det här exemplet stöder också "grab and pull" för att världslåsa menyn.

I det här exemplet blir menyn synlig och osynlig genom att aktivera objektet MenuContent på händelsen OnFirstHandDetected(). Med händelsen OnLastHandLost() aktiveras stängningsknappen och placeringsanimeringen utlöses. Animeringen är en enkel skalningsvariation. Eftersom vi inte dolde Händelsen MenuContent på OnLastHandLost() blir menyn automatiskt världslåst när handen inte visas. Värdena i avsnittet Palm Up har optimerats för att göra menyn världslåst utan att dras ned för mycket till hands.

Exempel på handmeny stor 1

Palm Up-konfiguration

Det här exemplet innehåller det handtagsbara fältet längst ned på menyn och det automatiska beteendet för världslåsning. Användaren kan uttryckligen koppla bort menyn från handen och placera den i världen genom att ta tag i den här. För att uppnå detta inaktiverar vi SolverHandler.UpdateSolvers i ManipulationStarted()-händelsen i ObjectManipulator. Annars kan menyn inte kopplas från eftersom HandConstraint-lösaren försöker placera menyn nära handpositionen. Vi använder också HandConstraintPalmUp.StartWorldLockReattachCheckCoroutine för att låta användaren höja handen för att återansluta menyn till handen.

Exempel på handmeny stor 2

Slutligen måste stängningsknappen återaktivera SolverHandler.UpdateSolvers för att återställa HandConstraint-lösarens funktioner.

Exempel på handmeny stor 3

Skript

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 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 solverspårade objektet när handflatan är riktad mot användaren.

Mer dokumentation finns i knappbeskrivningarna som är tillgängliga för varje HandConstraint egenskap. Några egenskaper definieras mer detaljerat nedan.

  • Säker zon: Den säkra zonen anger var till hands innehållet ska begränsas. Vi rekommenderar att innehåll placeras på Ulnar-sidan för att undvika överlappning med handen och förbättrad interaktionskvalitet. Säkra zoner beräknas enligt händernas orientering projicerade i ett plan ortoggonal till kamerans vy och raycasting mot en avgränsningslåda runt händerna. Säkra zoner definieras för att fungera med XRNode. Vi rekommenderar att du utforskar vad varje säker zon representerar på olika typer av styrenheter.

  • Följ hand tills kameran är riktad Med denna aktiva kommer lösaren att följa handrotationen tills menyn är tillräckligt justerad med blicken när den möter kameran. För att det här ska fungera ändrar du SolverRotationBehavior i HandConstraintSolver, från LookAtTrackedObject till LookAtMainCamera som vinkeln GazeAlignment med lösaren varierar.

Exempel på säker zon på handmeny

  • Aktiveringshändelser: För närvarande HandConstraint utlöser fyra aktiveringshändelser. Dessa händelser kan användas i många olika kombinationer för att skapa unika HandConstraint beteenden.

    • OnHandActivate: utlöses när en hand uppfyller metoden IsHandActive.
    • OnHandDeactivate: utlöses när metoden IsHandActive inte längre uppfylls.
    • OnFirstHandDetected: inträffar när tillståndet för handspårning ändras från inga händer i vyn till första hand i vyn.
    • OnLastHandLost: inträffar när tillståndet för handspårning ändras från minst en hand i vyn till inga händer i vyn.
  • Lösningsaktiverings-/inaktiveringslogik: För närvarande är rekommendationen för aktivering och inaktivering HandConstraintPalmUp av logik att göra det med hjälp SolverHandlerav värdet 's UpdateSolver i stället för att inaktivera/aktivera objektet. Detta kan ses i exempelscenen via de redigeringsbaserade krokarna som utlöses efter den anslutna menyns ManipulationHandler-händelser "OnManipulationStarted/Ended".

    • Stoppa logiken för handvillkor: När du försöker ställa in att det handbegränsade objektet ska stoppas (och inte köra aktiverings-/inaktiveringslogik) anger du UpdateSolver till False i stället för att inaktivera HandConstraintPalmUp.
      • Om du vill aktivera den blickbaserade (eller till och med icke-blickbaserade) återattach-logiken följs detta sedan av anrop till HandConstraintPalmUp.StartWorldLockReattachCheckCoroutine() funktionen. Detta utlöser en coroutine som fortsätter att kontrollera om kriterierna ärIsValidController uppfyllda och ställer in UpdateSolver på True när det är (eller om objektet är inaktiverat).
    • Startar logiken för handvillkor: När du försöker ange att det handbegränsade objektet ska börja följa din hand igen (baserat på om det uppfyller aktiveringskriterierna) anger du SolverHandlers UpdateSolver till true.
  • Återkoppla logik: För närvarande HandConstraintPalmUp kan automatiskt återkoppla målobjektet till den spårade punkten, oavsett om SolverHandler's UpdateSolver är Sant. Detta görs genom att anropa HandConstraintPalmUpfunktionen 's StartWorldLockReattachCheckCoroutine() när den har blivit världslåst (vilket i det här fallet i praktiken ställer in SolverHandlers UpdateSolver på False).