MR-indata 213: Rörelsestyrenheter

Anteckning

Självstudierna Mixed Reality Academy har utformats med HoloLens (första generationen) och Mixed Reality integrerande headset i åtanke. Därför anser vi att det är viktigt att låta de här självstudierna vara kvar för utvecklare som fortfarande letar efter vägledning för att utveckla för dessa enheter. De här självstudierna uppdateras inte med de senaste verktygsuppsättningarna eller interaktionerna som används för HoloLens 2. De underhålls för att fortsätta arbeta på de enheter som stöds. En ny serie självstudier har publicerats för HoloLens 2.

Rörelsekontrollanter i mixed reality-världen lägger till ytterligare en nivå av interaktivitet. Med rörelsekontrollanter kan vi direkt interagera med objekt på ett mer naturligt sätt, liknande våra fysiska interaktioner i verkliga livet, vilket ökar nedsänkningen och glädjen i din appupplevelse.

I MR Input 213 utforskar vi rörelsestyrenhetens indatahändelser genom att skapa en enkel rumslig målningsupplevelse. Med den här appen kan användarna måla i tredimensionellt utrymme med olika typer av penslar och färger.

Ämnen som beskrivs i den här självstudien

MixedReality213 Topic1 MixedReality213 Ämne2 MixedReality213 Ämne3
Visualisering av kontrollant Indatahändelser för kontrollant Anpassad kontrollant och användargränssnitt
Lär dig hur du renderar rörelsestyrenhetsmodeller i Unitys spelläge och körning. Förstå olika typer av knapphändelser och deras program. Lär dig hur du överlagr användargränssnittselement ovanpå kontrollanten eller anpassar dem fullständigt.

Stöd för enheter

Kurs HoloLens Integrerande headset
MR-indata 213: Rörelsestyrenheter ✔️

Innan du börjar

Förutsättningar

Se installationschecklistan för uppslukande headset på den här sidan.

Projektfiler

Anteckning

Om du vill titta igenom källkoden innan du laddar ned den är den tillgänglig på GitHub.

Unity-konfiguration

Mål

  • Optimera Unity för Windows Mixed Reality utveckling
  • Konfigurera Mixed Reality kamera
  • Konfigurera miljön

Instruktioner

  • Starta Unity.

  • Välj Öppna.

  • Gå till skrivbordet och leta reda på mappen MixedReality213-master som du tidigare inte har identifierat.

  • Klicka på Välj mapp.

  • När Unity har slutfört inläsningen av projektfiler kan du se Unity-redigeraren.

  • I Unity väljer du Inställningar för filbygge>.

    MR213_BuildSettings

  • Välj Universell Windows-plattform i listan Plattform och klicka på knappen Växla plattform.

  • Ange Målenhet till Valfri enhet

  • Ange Byggtyp till D3D

  • Ange SDK till Senast installerad

  • Kontrollera Unity C#-projekt

    • På så sätt kan du ändra skriptfiler i Visual Studio-projektet utan att återskapa Unity-projektet.
  • Klicka på Spelarinställningar.

  • Rulla ned till botten på panelen Kontroll

  • I XR-inställningar kontrollerar du virtual reality som stöds

  • Under Virtual Reality SDK:er väljer du Windows Mixed Reality

    MR213_XRSettings

  • Stäng fönstret Skapa inställningar .

Projektstruktur

I den här självstudien används Mixed Reality Toolkit – Unity. Du hittar versionerna på den här sidan.

ProjectStructure

Slutförda scener för referensen

  • Du hittar två färdiga Unity-scener under mappen Scener .
    • MixedReality213: Slutförd scen med en pensel
    • MixedReality213Avancerat: Slutförd scen för avancerad design med flera penslar

Ny scenkonfiguration för självstudien

  • I Unity klickar du på Arkiv > ny scen

  • Ta bort huvudkamera och riktningsljus

  • Från projektpanelen söker du och drar följande prefabs till panelen Hierarki :

    • Tillgångar/HoloToolkit/Input/Prefabs/MixedRealityCamera
    • Tillgångar/AppPrefabs/Miljö

    Kamera och miljö

  • Det finns två kameraprefabs i Mixed Reality Toolkit:

    • MixedRealityCamera.prefab: Endast kamera
    • MixedRealityCameraParent.prefab: Kamera + Teleportering + Gräns
    • I den här självstudien använder vi MixedRealityCamera utan teleporteringsfunktion. Därför har vi lagt till enkel miljöprefab som innehåller en grundläggande våning för att få användaren att känna sig jordad.
    • Mer information om teleportering med MixedRealityCameraParent finns i Avancerad design – teleportering och rörelse

Skybox-konfiguration

  • Klicka på Inställningar för fönsterbelysning >>

  • Klicka på cirkeln till höger i fältet Skybox Material

  • Skriv "grå" och välj SkyboxGray (Assets/AppPrefabs/Support/Materials/SkyboxGray.mat)

    Ange en himmelsruta

  • Markera alternativet Skybox för att kunna se tilldelad grå toningshimmelbox

    Växla alternativ för skybox

  • Scenen med MixedRealityCamera, Miljö och grå skybox kommer att se ut så här.

    MixedReality213-miljö

  • Klicka på Spara filscen > som

  • Spara scenen under mappen Scener med valfritt namn

Kapitel 1 – Kontrollantvisualisering

Mål

  • Lär dig hur du renderar modeller för rörelsestyrenhet i Unitys spelläge och vid körning.

Windows Mixed Reality tillhandahåller en animerad kontrollantmodell för kontrollantvisualisering. Det finns flera metoder som du kan använda för kontrollantvisualisering i din app:

  • Standard – Använda standardstyrenhet utan ändring
  • Hybrid – Använda standardstyrenhet, men anpassa vissa av dess element eller lägga över gränssnittskomponenter
  • Ersättning – Använda din egen anpassade 3D-modell för kontrollanten

I det här kapitlet får vi lära oss mer om exemplen på dessa anpassningar av kontrollanter.

Instruktioner

  • I projektpanelen skriver du MotionControllers i sökrutan . Du hittar den också under Tillgångar/HoloToolkit/Input/Prefabs/.
  • Dra prefab för MotionControllers till hierarkipanelen .
  • Klicka på prefab för MotionControllers i hierarkipanelen .

MotionControllers prefab

MotionControllers prefab har ett MotionControllerVisualizer-skript som tillhandahåller platser för alternativa styrenhetsmodeller. Om du tilldelar dina egna anpassade 3D-modeller, till exempel en hand eller ett svärd och markerar "Använd alltid alternativ vänster/höger modell", visas de i stället för standardmodellen. Vi kommer att använda det här facket i kapitel 4 för att ersätta styrenhetsmodellen med en borste.

MR213_ControllerVisualizer

Instruktioner

  • Dubbelklicka på MotionControllerVisualizer-skriptet på panelen Inspector för att se koden i Visual Studio

MotionControllerVisualizer-skript

Klasserna MotionControllerVisualizer och MotionControllerInfo ger möjlighet att komma åt & ändra standardstyrenhetsmodellerna. MotionControllerVisualizer prenumererar på Unitys InteractionSourceDetected-händelse och instansierar automatiskt kontrollantmodeller när de hittas.

protected override void Awake()
{
    ...
    InteractionManager.InteractionSourceDetected += InteractionManager_InteractionSourceDetected;
    InteractionManager.InteractionSourceLost += InteractionManager_InteractionSourceLost;
    ...
}

Styrenhetsmodellerna levereras enligt glTF-specifikationen. Det här formatet har skapats för att ge ett gemensamt format, samtidigt som processen bakom överföring och upppaketering av 3D-tillgångar förbättras. I det här fallet måste vi hämta och läsa in styrenhetsmodellerna vid körning, eftersom vi vill göra användarens upplevelse så smidig som möjligt, och det är inte garanterat vilken version av rörelsekontrollanterna som användaren använder. I den här kursen, via Mixed Reality Toolkit, används en version av Khronos Groups UnityGLTF-projekt.

När kontrollanten har levererats kan skript använda MotionControllerInfo för att hitta transformeringar för specifika kontrollantelement så att de kan placera sig själva korrekt.

I ett senare kapitel får vi lära oss hur du använder dessa skript för att koppla gränssnittselement till kontrollanterna.

I vissa skript hittar du kodblock med #if ! UNITY_EDITOR eller UNITY_WSA. Dessa kodblock körs endast på UWP-körningen när du distribuerar till Windows. Det beror på att den uppsättning API:er som används av Unity-redigeraren och UWP-appkörningen skiljer sig åt.

  • Spara scenen och klicka på uppspelningsknappen .

Du kommer att kunna se scenen med rörelsestyrenheter i headsetet. Du kan se detaljerade animeringar för knappklick, rörelse med tumstick och pekplatta.

standard för MR213_Controller visualisering

Kapitel 2 – Koppla gränssnittselement till kontrollanten

Mål

  • Lär dig mer om elementen i rörelsekontrollanterna
  • Lär dig hur du kopplar objekt till specifika delar av styrenheterna

I det här kapitlet får du lära dig hur du lägger till användargränssnittselement i kontrollanten som användaren enkelt kan komma åt och manipulera när som helst. Du får också lära dig hur du lägger till ett enkelt användargränssnitt för färgväljaren med hjälp av pekplattans indata.

Instruktioner

  • I projektpanelen söker du i MotionControllerInfo-skriptet .
  • Dubbelklicka på MotionControllerInfo-skriptet i sökresultatet för att se koden i Visual Studio.

MotionControllerInfo-skript

Det första steget är att välja vilket element i kontrollanten som du vill att användargränssnittet ska kopplas till. Dessa element definieras i ControllerElementEnum i MotionControllerInfo.cs.

MR213 MotionControllerElements

  • Start
  • Meny
  • Förstå
  • Styrspak
  • Välj
  • Touchpad
  • Pekposition – det här elementet representerar spetsen på styrenheten som pekar framåt.

Instruktioner

  • I projektpanelen söker du efter Skriptet AttachToController .
  • Dubbelklicka på AttachToController-skriptet i sökresultatet för att se koden i Visual Studio.

AttachToController-skript

AttachToController-skriptet är ett enkelt sätt att koppla alla objekt till en angiven handkontrollant och ett element.

I AttachElementToController(),

  • Kontrollera handlighet med MotionControllerInfo.Handedness
  • Hämta ett specifikt element i kontrollanten med Hjälp av MotionControllerInfo.TryGetElement()
  • När du har hämtat elementets transformering från kontrollantmodellen överordnas objektet under det och objektets lokala position & rotation till noll.
public MotionControllerInfo.ControllerElementEnum Element { get { return element; } }

private void AttachElementToController(MotionControllerInfo newController)
{
     if (!IsAttached && newController.Handedness == handedness)
     {
          if (!newController.TryGetElement(element, out elementTransform))
          {
               Debug.LogError("Unable to find element of type " + element + " under controller " + newController.ControllerParent.name + "; not attaching.");
               return;
          }

          controller = newController;

          SetChildrenActive(true);

          // Parent ourselves under the element and set our offsets
          transform.parent = elementTransform;
          transform.localPosition = positionOffset;
          transform.localEulerAngles = rotationOffset;
          if (setScaleOnAttach)
          {
               transform.localScale = scale;
          }

          // Announce that we're attached
          OnAttachToController();
          IsAttached = true;
     }
}

Det enklaste sättet att använda AttachToController-skriptet är att ärva från det, som vi har gjort när det gäller ColorPickerWheel. Åsidosätt bara funktionerna OnAttachToController och OnDetachFromController för att utföra konfigurationen/uppdelningen när kontrollanten identifieras/kopplas från.

Instruktioner

  • I panelen Projekt skriver du i sökrutan ColorPickerWheel. Du hittar den även under Tillgångar/AppPrefabs/.
  • Dra ColorPickerWheel-prefab till hierarkipanelen .
  • Klicka på prefab för ColorPickerWheel på panelen Hierarki .
  • Dubbelklicka på ColorPickerWheel Script på panelen Inspector för att se koden i Visual Studio.

ColorPickerWheel prefab

ColorPickerWheel-skript

Eftersom ColorPickerWheel ärver AttachToController visas Handedness och Element i panelen Inspector . Vi kommer att koppla användargränssnittet till Touchpad-elementet på den vänstra styrenheten.

ColorPickerWheel-skript

ColorPickerWheel åsidosätter OnAttachToController och OnDetachFromController för att prenumerera på indatahändelsen som kommer att användas i nästa kapitel för färgval med touchpad-indata.

public class ColorPickerWheel : AttachToController, IPointerTarget
{
    protected override void OnAttachToController()
    {
        // Subscribe to input now that we're parented under the controller
        InteractionManager.InteractionSourceUpdated += InteractionSourceUpdated;
    }

    protected override void OnDetachFromController()
    {
        Visible = false;

        // Unsubscribe from input now that we've detached from the controller
        InteractionManager.InteractionSourceUpdated -= InteractionSourceUpdated;
    }
    ...
}
  • Spara scenen och klicka på uppspelningsknappen .

Alternativ metod för att koppla objekt till kontrollanterna

Vi rekommenderar att skripten ärver från AttachToController och åsidosätter OnAttachToController. Detta kanske dock inte alltid är möjligt. Ett alternativ är att använda den som en fristående komponent. Detta kan vara användbart när du vill koppla en befintlig prefab till en kontrollant utan att omstrukturera dina skript. Låt bara klassen vänta tills IsAttached har angetts till true innan du utför någon konfiguration. Det enklaste sättet att göra detta är att använda en coroutine för "Start".

private IEnumerator Start() {
    AttachToController attach = gameObject.GetComponent<AttachToController>();

    while (!attach.IsAttached) {
        yield return null;
    }

    // Perform setup here
}

Kapitel 3 – Arbeta med pekplatta

Mål

  • Lär dig hur du hämtar indatahändelser för pekplatta
  • Lär dig hur du använder positionsinformation för pekplatta för din appupplevelse

Instruktioner

  • Klicka på ColorPickerWheel på panelen Hierarki
  • Dubbelklicka på ColorPickerWheelController under Animator på panelen Inspector
  • Du kommer att kunna se fliken Animator öppen

Visa/dölja användargränssnittet med Unitys animeringskontrollant

För att visa och dölja ColorPickerWheel-användargränssnittet med animering använder vi Unitys animeringssystem. Om du anger egenskapen Visible för ColorPickerWheel till true- eller false-utlösare visas och döljer du animeringsutlösare. Parametrarna Visa och Dölj definieras i animeringskontrollanten ColorPickerWheelController .

Unity Animation Controller

Instruktioner

  • Välj Prefab för ColorPickerWheel på panelen Hierarki
  • Dubbelklicka på ColorPickerWheel-skript på panelen Kontroll för att se koden i Visual Studio

ColorPickerWheel-skript

ColorPickerWheel prenumererar på Unitys InteractionSourceUpdated-händelse för att lyssna efter touchpad-händelser.

I InteractionSourceUpdated()kontrollerar skriptet först att det:

  • är faktiskt en pekplatta (obj.state.pekplattaTouched)
  • kommer från den vänstra kontrollanten (obj.state.source.handlighet)

Om båda är sanna, pekplattan position (obj.state.touchpadPosition) tilldelas till selectorPosition.

private void InteractionSourceUpdated(InteractionSourceUpdatedEventArgs obj)
{
    if (obj.state.source.handedness == handedness && obj.state.touchpadTouched)
    {
        Visible = true;
        selectorPosition = obj.state.touchpadPosition;
    }
}

I Update(), baserat på visible-egenskapen , utlöses utlösare för Visa och Dölj animering i färgväljarens animatörskomponent

if (visible != visibleLastFrame)
{
    if (visible)
    {
        animator.SetTrigger("Show");
    }
    else
    {
        animator.SetTrigger("Hide");
    }
}

I Update()används selectorPosition för att kasta en stråle vid färghjulets nät kolliderare, som returnerar en UV-position. Den här positionen kan sedan användas för att hitta pixelkoordinaten och färgvärdet för färghjulets struktur. Det här värdet är tillgängligt för andra skript via egenskapen SelectedColor .

Färgväljare Hjul Raycasting

...
    // Clamp selector position to a radius of 1
    Vector3 localPosition = new Vector3(selectorPosition.x * inputScale, 0.15f, selectorPosition.y * inputScale);
    if (localPosition.magnitude > 1)
    {
        localPosition = localPosition.normalized;
    }
    selectorTransform.localPosition = localPosition;

    // Raycast the wheel mesh and get its UV coordinates
    Vector3 raycastStart = selectorTransform.position + selectorTransform.up * 0.15f;
    RaycastHit hit;
    Debug.DrawLine(raycastStart, raycastStart - (selectorTransform.up * 0.25f));

    if (Physics.Raycast(raycastStart, -selectorTransform.up, out hit, 0.25f, 1 << colorWheelObject.layer, QueryTriggerInteraction.Ignore))
    {
        // Get pixel from the color wheel texture using UV coordinates
        Vector2 uv = hit.textureCoord;
        int pixelX = Mathf.FloorToInt(colorWheelTexture.width * uv.x);
        int pixelY = Mathf.FloorToInt(colorWheelTexture.height * uv.y);
        selectedColor = colorWheelTexture.GetPixel(pixelX, pixelY);
        selectedColor.a = 1f;
    }
    // Set the selector's color and blend it with white to make it visible on top of the wheel
    selectorRenderer.material.color = Color.Lerp (selectedColor, Color.white, 0.5f);
}

Kapitel 4 – Åsidosättande kontrollantmodell

Mål

  • Lär dig hur du åsidosätter kontrollantmodellen med en anpassad 3D-modell.

MR213_BrushToolOverride

Instruktioner

  • Klicka på MotionControllers på panelen Hierarki .
  • Klicka på cirkeln till höger i fältet Alternativ högerkontrollant .
  • Skriv "BrushController" och välj prefab i resultatet. Du hittar den under Assets/AppPrefabs/BrushController.
  • Markera Använd alltid alternativ högermodell

MR213_BrushToolOverrideSlot

BrushController-prefab behöver inte tas med på panelen Hierarki. Men för att kolla in dess underordnade komponenter:

  • På panelen Projekt skriver du BrushController och drar BrushController prefab till panelen Hierarki .

MR213_BrushTool_Prefab2

Tipskomponenten finns i BrushController. Vi använder dess transformering för att starta/stoppa ritlinjer.

  • Ta bort BrushController från panelen Hierarki .
  • Spara scenen och klicka på uppspelningsknappen. Du kommer att kunna se att penselmodellen ersatte den högra rörelsestyrenheten.

Kapitel 5 - Målning med Select-indata

Mål

  • Lär dig hur du använder händelsen Välj knapp för att starta och stoppa en linjeritning

Instruktioner

  • Sök i BrushController-prefabprojektpanelen .
  • Dubbelklicka på BrushController Script på panelen Inspector för att se koden i Visual Studio

BrushController-skript

BrushController prenumererar på InteractionManagers InteractionSourcePressed - och InteractionSourceReleased-händelser . När InteractionSourcePressed-händelsen utlöses anges penselns draw-egenskap till true. när InteractionSourceReleased-händelsen utlöses anges penselns draw-egenskap till false.

private void InteractionSourcePressed(InteractionSourcePressedEventArgs obj)
{
    if (obj.state.source.handedness == InteractionSourceHandedness.Right && obj.pressType == InteractionSourcePressType.Select)
    {
        Draw = true;
    }
}

private void InteractionSourceReleased(InteractionSourceReleasedEventArgs obj)
{
    if (obj.state.source.handedness == InteractionSourceHandedness.Right && obj.pressType == InteractionSourcePressType.Select)
    {
        Draw = false;
    }
}

Även om Draw är inställt på sant genererar penseln punkter i en instansierad Unity LineRenderer. En referens till den här prefab förvaras i penselns linjeprefabfält .

private IEnumerator DrawOverTime()
{
    // Get the position of the tip
    Vector3 lastPointPosition = tip.position;

    ...

    // Create a new brush stroke
    GameObject newStroke = Instantiate(strokePrefab);
    LineRenderer line = newStroke.GetComponent<LineRenderer>();
    newStroke.transform.position = startPosition;
    line.SetPosition(0, tip.position);
    float initialWidth = line.widthMultiplier;

    // Generate points in an instantiated Unity LineRenderer
    while (draw)
    {
        // Move the last point to the draw point position
        line.SetPosition(line.positionCount - 1, tip.position);
        line.material.color = colorPicker.SelectedColor;
        brushRenderer.material.color = colorPicker.SelectedColor;
        lastPointAddedTime = Time.unscaledTime;
        // Adjust the width between 1x and 2x width based on strength of trigger pull
        line.widthMultiplier = Mathf.Lerp(initialWidth, initialWidth * 2, width);

        if (Vector3.Distance(lastPointPosition, tip.position) > minPositionDelta || Time.unscaledTime > lastPointAddedTime + maxTimeDelta)
        {
            // Spawn a new point
            lastPointAddedTime = Time.unscaledTime;
            lastPointPosition = tip.position;
            line.positionCount += 1;
            line.SetPosition(line.positionCount - 1, lastPointPosition);
        }
        yield return null;
    }
}

Om du vill använda den markerade färgen från användargränssnittet för färgväljarens hjul måste BrushController ha en referens till ColorPickerWheel-objektet . Eftersom BrushController-prefab instansieras vid körning som en ersättningskontrollant, måste alla referenser till objekt i scenen anges vid körning. I det här fallet använder vi GameObject.FindObjectOfType för att hitta ColorPickerWheel:

private void OnEnable()
{
    // Locate the ColorPickerWheel
    colorPicker = FindObjectOfType<ColorPickerWheel>();

    // Assign currently selected color to the brush’s material color
    brushRenderer.material.color = colorPicker.SelectedColor;
    ...
}
  • Spara scenen och klicka på uppspelningsknappen. Du kommer att kunna rita linjerna och måla med hjälp av välj-knappen på den högra styrenheten.

Kapitel 6 – Objektlekning med Select-indata

Mål

  • Lär dig hur du använder indatahändelser för Knappen Välj och Greppa
  • Lär dig hur du instansierar objekt

Instruktioner

  • I projektpanelen skriver du ObjectSpawner i sökrutan. Du hittar den även under Tillgångar/AppPrefabs/

  • Dra prefab för ObjectSpawner till panelen Hierarki .

  • Klicka på ObjectSpawner på panelen Hierarki .

  • ObjectSpawner har ett fält med namnet Color Source.

  • Dra referensen ColorPickerWheel från panelen Hierarki till det här fältet.

    Objektskaparkontroll

  • Klicka på prefab för ObjectSpawner på panelen Hierarki .

  • I panelen Inspector dubbelklickar du på ObjectSpawner Script för att se koden i Visual Studio.

ObjectSpawner-skript

ObjectSpawner instansierar kopior av ett primitivt nät (kub, sfär, cylinder) i utrymmet. När en InteractionSourcePressed identifieras kontrollerar den handligheten och om det är en InteractionSourcePressType.Grasp - eller InteractionSourcePressType.Select-händelse .

För en Grip-händelse ökar den indexet för aktuell nättyp (sfär, kub, cylinder)

private void InteractionSourcePressed(InteractionSourcePressedEventArgs obj)
{
    // Check handedness, see if it is left controller
    if (obj.state.source.handedness == handedness)
    {
        switch (obj.pressType)
        {
            // If it is Select button event, spawn object
            case InteractionSourcePressType.Select:
                if (state == StateEnum.Idle)
                {
                    // We've pressed the grasp - enter spawning state
                    state = StateEnum.Spawning;
                    SpawnObject();
                }
                break;

            // If it is Grasp button event
            case InteractionSourcePressType.Grasp:

                // Increment the index of current mesh type (sphere, cube, cylinder)
                meshIndex++;
                if (meshIndex >= NumAvailableMeshes)
                {
                    meshIndex = 0;
                }
                break;

            default:
                break;
        }
    }
}

För en Select-händelse , i SpawnObject(), instansieras ett nytt objekt, inte är överordnat och släpps ut i världen.

private void SpawnObject()
{
    // Instantiate the spawned object
    GameObject newObject = Instantiate(displayObject.gameObject, spawnParent);
    // Detach the newly spawned object
    newObject.transform.parent = null;
    // Reset the scale transform to 1
    scaleParent.localScale = Vector3.one;
    // Set its material color so its material gets instantiated
    newObject.GetComponent<Renderer>().material.color = colorSource.SelectedColor;
}

ObjectSpawner använder ColorPickerWheel för att ange färgen på visningsobjektets material. Lekobjekt får en instans av det här materialet så att de behåller sin färg.

  • Spara scenen och klicka på uppspelningsknappen.

Du kommer att kunna ändra objekten med knappen Grip och skapa objekt med knappen Välj.

Skapa och distribuera en app till Mixed Reality-portalen

  • I Unity väljer du Inställningar för filbygge>.
  • Klicka på Lägg till öppna scener för att lägga till aktuell scen i Scenes In Build.
  • Klicka på Skapa.
  • Skapa en ny mapp med namnet "App".
  • Klicka på mappen App .
  • Klicka på Välj mapp.
  • När Unity är klart visas ett Utforskaren fönster.
  • Öppna mappen App .
  • Dubbelklicka på filen YourSceneName.sln Visual Studio Solution.
  • Använd det översta verktygsfältet i Visual Studio och ändra målet från Felsökning till Släpp och från ARM till X64.
  • Klicka på listrutepilen bredvid knappen Enhet och välj Lokal dator.
  • Klicka på Felsök –> Starta utan felsökning på menyn eller tryck på Ctrl + F5.

Nu har appen skapats och installerats i Mixed Reality-portalen. Du kan starta den igen via Start-menyn i Mixed Reality-portalen.

Avancerad design – Borstverktyg med radiell layout

MixedReality213 Main

I det här kapitlet får du lära dig hur du ersätter standardmodellen för rörelsekontrollanten med en anpassad borstverktygssamling. Som referens hittar du den färdiga scenen MixedReality213Avancerat under mappen Scener .

Instruktioner

  • I panelen Projekt skriver du BrushSelector i sökrutan . Du hittar den även under Tillgångar/AppPrefabs/

  • Dra förfab för BrushSelector till panelen Hierarki .

  • För organisationen skapar du ett tomt GameObject med namnet Brushes

  • Dra följande prefabs från projektpanelen till Penslar

    • Assets/AppPrefabs/BrushFat
    • Assets/AppPrefabs/BrushThin
    • Assets/AppPrefabs/Eraser
    • Tillgångar/AppPrefabs/MarkerFat
    • Assets/AppPrefabs/MarkerThin
    • Tillgångar/AppPrefabs/Penna

    Penslar

  • Klicka på Prefab för MotionControllers på panelen Hierarki .

  • Avmarkera Använd alltid alternativ högermodellVisualiseraren för rörelsestyrenhetpanelen Kontroll

  • På panelen Hierarki klickar du på BrushSelector

  • BrushSelector har ett fält med namnet ColorPicker

  • Dra fältet ColorPickerWheel till Fältet ColorPickerpanelen Kontroll från panelen Hierarki.

    Tilldela ColorPickerWheel till penselväljaren

  • Välj menyobjektetunderBrushSelector prefab på hierarkipanelen.

  • Öppna listrutan Objektmatris under komponenten LineObjectCollection på panelen Kontroll. Du ser 6 tomma platser.

  • Dra var och en av de överordnade prefaberna under Penslar GameObject till dessa platser i valfri ordning från hierarkipanelen. (Se till att du drar prefaberna från scenen, inte prefaberna i projektmappen.)

Penselväljare

BrushSelector-prefab

Eftersom BrushSelector ärver AttachToController visas alternativen Handedness och Element i panelen Inspector . Vi valde Höger och Pekar pose för att fästa borstverktygen på den högra styrenheten med framåtriktad riktning.

BrushSelector använder två verktyg:

  • Ellips: används för att generera punkter i rymden längs en ellipsform.
  • LineObjectCollection: distribuerar objekt med hjälp av de punkter som genereras av valfri linjeklass (t.ex. Ellips). Detta är vad vi kommer att använda för att placera våra penslar längs Ellipsformen.

När de kombineras kan dessa verktyg användas för att skapa en radiell meny.

LineObjectCollection-skript

LineObjectCollection har kontroller för storlek, position och rotation av objekt som distribueras längs linjen. Detta är användbart för att skapa radiella menyer som penselväljaren. För att skapa utseendet på penslar som skalas upp från ingenting när de närmar sig den valda mittenpositionen, toppar ObjectScale-kurvan i mitten och avsmalnas vid kanterna.

BrushSelector-skript

När det gäller BrushSelector har vi valt att använda proceduranimering. Först distribueras penselmodeller i en ellips av LineObjectCollection-skriptet . Sedan ansvarar varje pensel för att behålla sin position i användarens hand baserat på dess DisplayMode-värde , som ändras baserat på markeringen. Vi valde en procedurmetod på grund av den höga sannolikheten för att penselpositionsövergångar avbryts när användaren väljer penslar. Mecanim-animeringar kan hantera avbrott på ett smidigt sätt, men det brukar vara mer komplicerat än en enkel Lerp-åtgärd.

BrushSelector använder en kombination av båda. När pekplattans indata identifieras blir penselalternativen synliga och skalas upp längs radiell meny. Efter en tidsgräns (vilket indikerar att användaren har gjort ett val) skalar penselalternativen ned igen och lämnar bara den valda penseln.

Visualisera indata för pekplatta

Även om styrenhetsmodellen har ersatts helt kan det vara bra att visa indata på de ursprungliga modellindata. Detta hjälper till att grunda användarens åtgärder i verkligheten. För BrushSelector har vi valt att göra pekplattan kort synlig när indata tas emot. Detta gjordes genom att hämta Touchpad-elementet från styrenheten, ersätta dess material med ett anpassat material och sedan tillämpa en toning på materialets färg baserat på den senaste gången pekplattans indata togs emot.

protected override void OnAttachToController()
{
    // Turn off the default controller's renderers
    controller.SetRenderersVisible(false);

    // Get the touchpad and assign our custom material to it
    Transform touchpad;
    if (controller.TryGetElement(MotionControllerInfo.ControllerElementEnum.Touchpad, out touchpad))
    {
        touchpadRenderer = touchpad.GetComponentInChildren<MeshRenderer>();
        originalTouchpadMaterial = touchpadRenderer.material;
        touchpadRenderer.material = touchpadMaterial;
        touchpadRenderer.enabled = true;
    }

    // Subscribe to input now that we're parented under the controller
    InteractionManager.InteractionSourceUpdated += InteractionSourceUpdated;
}

private void Update()
{
    ...
    // Update our touchpad material
    Color glowColor = touchpadColor.Evaluate((Time.unscaledTime - touchpadTouchTime) / touchpadGlowLossTime);
    touchpadMaterial.SetColor("_EmissionColor", glowColor);
    touchpadMaterial.SetColor("_Color", glowColor);
    ...
}

Markering av penselverktyg med touchpad-indata

När penselväljaren identifierar pekplattans inmatade indata kontrollerar den positionen för indata för att avgöra om det var till vänster eller höger.

Linjetjocklek med selectPressedAmount

I stället för händelsen InteractionSourcePressType.Select i InteractionSourcePressed()kan du hämta det analoga värdet för det nedtryckta beloppet via selectPressedAmount. Det här värdet kan hämtas i InteractionSourceUpdated().

private void InteractionSourceUpdated(InteractionSourceUpdatedEventArgs obj)
{
    if (obj.state.source.handedness == handedness)
    {
        if (obj.state.touchpadPressed)
        {
            // Check which side we clicked
            if (obj.state.touchpadPosition.x < 0)
            {
                currentAction = SwipeEnum.Left;
            }
            else
            {
                currentAction = SwipeEnum.Right;
            }

            // Ping the touchpad material so it gets bright
            touchpadTouchTime = Time.unscaledTime;
        }

        if (activeBrush != null)
        {
            // If the pressed amount is greater than our threshold, draw
            if (obj.state.selectPressedAmount >= selectPressedDrawThreshold)
            {
                activeBrush.Draw = true;
                activeBrush.Width = ProcessSelectPressedAmount(obj.state.selectPressedAmount);
            }
            else
            {
                // Otherwise, stop drawing
                activeBrush.Draw = false;
                selectPressedSmooth = 0f;
            }
        }
    }
}

Radergummiskript

Radergummi är en särskild typ av pensel som åsidosätter basborstens DrawOverTime()-funktion. Även om Draw är sant kontrollerar raderaren om dess spets korsar några befintliga penseldrag. Om den gör det läggs de till i en kö för att krympas ned och tas bort.

Avancerad design – Teleportering och rörelse

Om du vill tillåta att användaren flyttar runt scenen med teleportering med hjälp av tumstickan använder du MixedRealityCameraParent i stället för MixedRealityCamera. Du måste också lägga till InputManager och DefaultCursor. Eftersom MixedRealityCameraParent redan innehåller MotionControllers och Boundary som underordnade komponenter bör du ta bort befintliga MotionControllers och miljöprefab .

Instruktioner

  • Ta bort MixedRealityCamera, Environment och MotionControllers hierarkipanelen

  • Från projektpanelen söker du och drar följande prefabs till panelen Hierarki :

    • Tillgångar/AppPrefabs/Input/Prefabs/MixedRealityCameraParent
    • Tillgångar/AppPrefabs/Input/Prefabs/InputManager
    • Tillgångar/AppPrefabs/Input/Prefabs/Cursor/DefaultCursor

    Mixed Reality kamera överordnad

  • Klicka på Indatahanteraren på panelen Hierarki

  • Rulla ned till avsnittet Simple Single Pointer Selector (Enkel pekare) på panelen Inspector (Kontroll)

  • Dra DefaultCursor till markörfältet på panelen Hierarki

    Tilldela DefaultCursor

  • Spara scenen och klicka på uppspelningsknappen . Du kommer att kunna använda tumsticken för att rotera vänster/höger eller teleportering.

Slutet

Och det är slutet på den här självstudien! Du har lärt dig att:

  • Så här arbetar du med rörelsestyrenhetsmodeller i Unitys spelläge och körning.
  • Använda olika typer av knapphändelser och deras program.
  • Så här överlagr du gränssnittselement ovanpå kontrollanten eller anpassar det helt.

Nu är du redo att börja skapa en egen uppslukande upplevelse med rörelsestyrenheter!

Slutförda scener

  • I Unitys projektpanel klickar du på mappen Scener .
  • Du hittar två Unity-scener MixedReality213 och MixedReality213Advanced.
    • MixedReality213: Slutförd scen med en pensel
    • MixedReality213Avancerat: Slutförd scen med flera pensel med knappen Select i exemplet med tryckmängd

Se även