Dela via


HoloLens (första generationen) Grunder 101E: Slutför projektet med emulatorn

Viktigt

Självstudierna Mixed Reality Academy har utformats med HoloLens (första generationen), Unity 2017 och Mixed Reality integrerande headset i åtanke. Därför tycker vi att det är viktigt att låta de här självstudierna vara kvar för utvecklare som fortfarande behöver 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 och kanske inte är kompatibla med nyare versioner av Unity. De kommer att underhållas för att fortsätta arbeta på de enheter som stöds. En ny serie självstudier har publicerats för HoloLens 2.


Den här självstudien vägleder dig genom ett komplett projekt, inbyggt i Unity, som visar grundläggande Windows Mixed Reality funktioner på HoloLens, inklusive blick, gester, röstinmatning, rumsligt ljud och rumslig mappning. Självstudien tar cirka 1 timme att slutföra.

Stöd för enheter

Kurs HoloLens Integrerande headset
MR Basics 101E: Slutför projektet med emulatorn ✔️

Innan du börjar

Förutsättningar

Projektfiler

  • Ladda ned de filer som krävs av projektet. Kräver Unity 2017.2 eller senare.
  • Avarkivera filerna på skrivbordet eller på en annan plats som är lätt att nå. Behåll mappnamnet som Origami.

Anteckning

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

Kapitel 1 - "Holo"-världen

I det här kapitlet ska vi konfigurera vårt första Unity-projekt och gå igenom bygg- och distributionsprocessen.

Mål

  • Konfigurera Unity för holografisk utveckling.
  • Skapa ett hologram.
  • Se ett hologram som du har skapat.

Instruktioner

  • Starta Unity.
  • Välj Öppna.
  • Ange plats som mappen Origami som du tidigare avarkiverade.
  • Välj Origami och klicka på Välj mapp.
  • Spara den nya scenen: Spara / scen som.
  • Ge scenen namnet Origami och tryck på knappen Spara .

Konfigurera huvudkameran

  • I hierarkipanelen väljer du Huvudkamera.
  • I inspektören anger du dess transformeringsposition till 0,0,0.
  • Leta reda på egenskapen Clear Flags och ändra listrutan från Skybox till Solid color.
  • Klicka på fältet Bakgrund för att öppna en färgväljare.
  • Ange R, G, B och A till 0.

Konfigurera scenen

  • I hierarkipanelen klickar du på Skapa och skapa tom.
  • Högerklicka på det nya GameObject och välj Byt namn. Byt namn på GameObject till PopupCollection.
  • Från mappen Hologramprojektpanelen:
    • Dra Stage (Fas ) till Hierarchy (Hierarki) för att vara underordnad OrigamiCollection.
    • Dra Sphere1 till hierarkin för att vara underordnad OrigamiCollection.
    • Dra Sphere2 till hierarkin för att vara underordnad OrigamiCollection.
  • Högerklicka på objektet Directional Light (Riktningsljus ) på hierarkipanelen och välj Ta bort.
  • Dra Lampor från mappen Hologram till roten på hierarkipanelen.
  • I hierarkin väljer du DensarinCollection.
  • I Inspector anger du transformeringspositionen till 0, -0,5, 2.0.
  • Tryck på knappen Spela upp i Unity för att förhandsgranska dina hologram.
  • Du bör se Origami-objekten i förhandsgranskningsfönstret.
  • Tryck på Spela upp en andra gång för att stoppa förhandsgranskningsläget.

Exportera projektet från Unity till Visual Studio

  • I Unity väljer du Inställningar för filbygge>.
  • Välj Windows Store i listan Plattform och klicka på Växla plattform.
  • Ange SDK till Universal 10 och Build Type till D3D.
  • Kontrollera Unity C#-projekt.
  • Klicka på Lägg till öppna scener för att lägga till scenen.
  • Klicka på Spelarinställningar....
  • I Kontrollpanelen väljer du Windows Store-logotypen. Välj sedan Publiceringsinställningar.
  • I avsnittet Funktioner väljer du funktionerna Mikrofon och SpatialPerception .
  • I fönstret Build Settings (Bygginställningar) klickar du på Build (Skapa).
  • Skapa en ny mapp med namnet "App".
  • Klicka på appmappen.
  • Tryck på Välj mapp.
  • När Unity är klart visas ett Utforskaren fönster.
  • Öppna mappen App .
  • Öppna Visual Studio-lösningen för Origami.
  • 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 X86.
    • Klicka på pilen bredvid knappen Enhet och välj HoloLens-emulatorn.
    • Klicka på Felsök –> Starta utan felsökning eller tryck på Ctrl + F5.
    • Efter en stund börjar emulatorn med Origami-projektet. När du först startar emulatorn kan det ta upp till 15 minuter innan emulatorn startas. När den startar ska du inte stänga den.

Kapitel 2 - Blick

I det här kapitlet ska vi introducera det första av tre sätt att interagera med dina hologram – blick.

Mål

  • Visualisera blicken med hjälp av en världslåst markör.

Instruktioner

  • Gå tillbaka till Unity-projektet och stäng fönstret Build Settings (Bygginställningar) om det fortfarande är öppet.
  • Välj mappen Hologram påpanelen Projekt.
  • Dra markörobjektet till panelen Hierarki på rotnivå.
  • Dubbelklicka på markörobjektet för att ta en närmare titt på det.
  • Högerklicka på mappen Skript i projektpanelen.
  • Klicka på undermenyn Skapa .
  • Välj C#-skript.
  • Ge skriptet namnet WorldCursor. Obs! Namnet är skiftlägeskänsligt. Du behöver inte lägga till tillägget .cs.
  • Välj markörens objekt på hierarkipanelen.
  • Dra och släpp WorldCursor-skriptet i panelen Inspector.
  • Dubbelklicka på WorldCursor-skriptet för att öppna det i Visual Studio.
  • Kopiera och klistra in den här koden i WorldCursor.cs och Spara alla.
using UnityEngine;

public class WorldCursor : MonoBehaviour
{
    private MeshRenderer meshRenderer;

    // Use this for initialization
    void Start()
    {
        // Grab the mesh renderer that's on the same object as this script.
        meshRenderer = this.gameObject.GetComponentInChildren<MeshRenderer>();
    }

    // Update is called once per frame
    void Update()
    {
        // Do a raycast into the world based on the user's
        // head position and orientation.
        var headPosition = Camera.main.transform.position;
        var gazeDirection = Camera.main.transform.forward;

        RaycastHit hitInfo;

        if (Physics.Raycast(headPosition, gazeDirection, out hitInfo))
        {
            // If the raycast hit a hologram...
            // Display the cursor mesh.
            meshRenderer.enabled = true;

            // Move thecursor to the point where the raycast hit.
            this.transform.position = hitInfo.point;

            // Rotate the cursor to hug the surface of the hologram.
            this.transform.rotation = Quaternion.FromToRotation(Vector3.up, hitInfo.normal);
        }
        else
        {
            // If the raycast did not hit a hologram, hide the cursor mesh.
            meshRenderer.enabled = false;
        }
    }
}
  • Återskapa appen från Inställningar för filskapning>.
  • Gå tillbaka till Visual Studio-lösningen som tidigare användes för att distribuera till emulatorn.
  • Välj "Ladda in alla igen" när du uppmanas att göra det.
  • Klicka på Felsök –> Starta utan att felsöka eller tryck på Ctrl + F5.
  • Använd Xbox-kontrollanten för att se dig omkring i scenen. Observera hur markören interagerar med objektens form.

Kapitel 3 – Gester

I det här kapitlet lägger vi till stöd för gester. När användaren väljer en papperssfär får vi sfären att falla genom att aktivera gravitationen med hjälp av Unitys fysikmotor.

Mål

  • Kontrollera dina hologram med gesten Välj.

Instruktioner

Vi börjar med att skapa ett skript än vad som kan identifiera select-gesten.

  • I mappen Skript skapar du ett skript med namnet GazeGestureManager.
  • Dra skriptet GazeGestureManager till objektet OrigamiCollection i hierarkin.
  • Öppna GazeGestureManager-skriptet i Visual Studio och lägg till följande kod:
using UnityEngine;
using UnityEngine.XR.WSA.Input;

public class GazeGestureManager : MonoBehaviour
{
    public static GazeGestureManager Instance { get; private set; }

    // Represents the hologram that is currently being gazed at.
    public GameObject FocusedObject { get; private set; }

    GestureRecognizer recognizer;

    // Use this for initialization
    void Start()
    {
        Instance = this;

        // Set up a GestureRecognizer to detect Select gestures.
        recognizer = new GestureRecognizer();
        recognizer.Tapped += (args) =>
        {
            // Send an OnSelect message to the focused object and its ancestors.
            if (FocusedObject != null)
            {
                FocusedObject.SendMessageUpwards("OnSelect", SendMessageOptions.DontRequireReceiver);
            }
        };
        recognizer.StartCapturingGestures();
    }

    // Update is called once per frame
    void Update()
    {
        // Figure out which hologram is focused this frame.
        GameObject oldFocusObject = FocusedObject;

        // Do a raycast into the world based on the user's
        // head position and orientation.
        var headPosition = Camera.main.transform.position;
        var gazeDirection = Camera.main.transform.forward;

        RaycastHit hitInfo;
        if (Physics.Raycast(headPosition, gazeDirection, out hitInfo))
        {
            // If the raycast hit a hologram, use that as the focused object.
            FocusedObject = hitInfo.collider.gameObject;
        }
        else
        {
            // If the raycast did not hit a hologram, clear the focused object.
            FocusedObject = null;
        }

        // If the focused object changed this frame,
        // start detecting fresh gestures again.
        if (FocusedObject != oldFocusObject)
        {
            recognizer.CancelGestures();
            recognizer.StartCapturingGestures();
        }
    }
}
  • Skapa ett annat skript i mappen Skript, den här gången med namnet SphereCommands.
  • Expandera objektet OrigamiCollection i hierarkivyn.
  • Dra SphereCommands-skriptet till Sphere1-objektet på hierarkipanelen.
  • Dra SphereCommands-skriptet till Sphere2-objektet på hierarkipanelen.
  • Öppna skriptet i Visual Studio för redigering och ersätt standardkoden med följande:
using UnityEngine;

public class SphereCommands : MonoBehaviour
{
    // Called by GazeGestureManager when the user performs a Select gesture
    void OnSelect()
    {
        // If the sphere has no Rigidbody component, add one to enable physics.
        if (!this.GetComponent<Rigidbody>())
        {
            var rigidbody = this.gameObject.AddComponent<Rigidbody>();
            rigidbody.collisionDetectionMode = CollisionDetectionMode.Continuous;
        }
    }
}
  • Exportera, skapa och distribuera appen till HoloLens-emulatorn.
  • Titta runt scenen och centrera på en av sfärerna.
  • Tryck på knappen A på Xbox-styrenheten eller tryck på Blanksteg för att simulera gesten Välj.

Kapitel 4 - Röst

I det här kapitlet lägger vi till stöd för två röstkommandon: "Återställ världen" för att returnera de borttagna sfärerna till sin ursprungliga plats och "Drop sphere" för att få sfären att falla.

Mål

  • Lägg till röstkommandon som alltid lyssnar i bakgrunden.
  • Skapa ett hologram som reagerar på ett röstkommando.

Instruktioner

  • Skapa ett skript med namnet SpeechManager i mappen Skript.
  • Dra SpeechManager-skriptet till OrigamiCollection-objektet i hierarkin
  • Öppna SpeechManager-skriptet i Visual Studio.
  • Kopiera och klistra in den här koden i SpeechManager.cs och Spara alla:
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.Windows.Speech;

public class SpeechManager : MonoBehaviour
{
    KeywordRecognizer keywordRecognizer = null;
    Dictionary<string, System.Action> keywords = new Dictionary<string, System.Action>();

    // Use this for initialization
    void Start()
    {
        keywords.Add("Reset world", () =>
        {
            // Call the OnReset method on every descendant object.
            this.BroadcastMessage("OnReset");
        });

        keywords.Add("Drop Sphere", () =>
        {
            var focusObject = GazeGestureManager.Instance.FocusedObject;
            if (focusObject != null)
            {
                // Call the OnDrop method on just the focused object.
                focusObject.SendMessage("OnDrop", SendMessageOptions.DontRequireReceiver);
            }
        });

        // Tell the KeywordRecognizer about our keywords.
        keywordRecognizer = new KeywordRecognizer(keywords.Keys.ToArray());

        // Register a callback for the KeywordRecognizer and start recognizing!
        keywordRecognizer.OnPhraseRecognized += KeywordRecognizer_OnPhraseRecognized;
        keywordRecognizer.Start();
    }

    private void KeywordRecognizer_OnPhraseRecognized(PhraseRecognizedEventArgs args)
    {
        System.Action keywordAction;
        if (keywords.TryGetValue(args.text, out keywordAction))
        {
            keywordAction.Invoke();
        }
    }
}
  • Öppna SphereCommands-skriptet i Visual Studio.
  • Uppdatera skriptet så att det läse så här:
using UnityEngine;

public class SphereCommands : MonoBehaviour
{
    Vector3 originalPosition;

    // Use this for initialization
    void Start()
    {
        // Grab the original local position of the sphere when the app starts.
        originalPosition = this.transform.localPosition;
    }

    // Called by GazeGestureManager when the user performs a Select gesture
    void OnSelect()
    {
        // If the sphere has no Rigidbody component, add one to enable physics.
        if (!this.GetComponent<Rigidbody>())
        {
            var rigidbody = this.gameObject.AddComponent<Rigidbody>();
            rigidbody.collisionDetectionMode = CollisionDetectionMode.Continuous;
        }
    }

    // Called by SpeechManager when the user says the "Reset world" command
    void OnReset()
    {
        // If the sphere has a Rigidbody component, remove it to disable physics.
        var rigidbody = this.GetComponent<Rigidbody>();
        if (rigidbody != null)
        {
            rigidbody.isKinematic = true;
            Destroy(rigidbody);
        }

        // Put the sphere back into its original local position.
        this.transform.localPosition = originalPosition;
    }

    // Called by SpeechManager when the user says the "Drop sphere" command
    void OnDrop()
    {
        // Just do the same logic as a Select gesture.
        OnSelect();
    }
}
  • Exportera, skapa och distribuera appen till HoloLens-emulatorn.
  • Emulatorn stöder datorns mikrofon och svarar på din röst: justera vyn så att markören är på en av sfärerna och säg "Drop Sphere".
  • Säg "Återställ världen" för att få dem tillbaka till sina ursprungliga positioner.

Kapitel 5 – Rumsligt ljud

I det här kapitlet ska vi lägga till musik i appen och sedan utlösa ljudeffekter på vissa åtgärder. Vi kommer att använda rumsligt ljud för att ge ljud en specifik plats i 3D-utrymme.

Mål

  • Hör hologram i din värld.

Instruktioner

  • I Unity väljer du på den översta menyn Redigera > projektinställningar > Ljud
  • Leta upp spatialiserarens plugin-inställning och välj MS HRTF Spatializer.
  • Dra objektet Ambience från mappen Holograms till objektet OrigamiCollection på hierarkipanelen.
  • Välj OrigamiCollection och leta reda på komponenten Ljudkälla . Ändra följande egenskaper:
    • Kontrollera egenskapen Spatialize .
    • Kontrollera uppspelningen på vaken.
    • Ändra Spatial Blend till 3D genom att dra skjutreglaget hela vägen till höger.
    • Kontrollera egenskapen Loop .
    • Expandera 3D-ljudinställningar och ange 0.1 för Doppler-nivå.
    • Ange Volymavrullning till Logarithmic Rolloff.
    • Ange Maxavstånd till 20.
  • Skapa ett skript med namnet SphereSounds i mappen Skript.
  • Dra SphereSounds till Sphere1 - och Sphere2-objekten i hierarkin.
  • Öppna SphereSounds i Visual Studio, uppdatera följande kod och Spara alla.
using UnityEngine;

public class SphereSounds : MonoBehaviour
{
    AudioSource impactAudioSource = null;
    AudioSource rollingAudioSource = null;

    bool rolling = false;

    void Start()
    {
        // Add an AudioSource component and set up some defaults
        impactAudioSource = gameObject.AddComponent<AudioSource>();
        impactAudioSource.playOnAwake = false;
        impactAudioSource.spatialize = true;
        impactAudioSource.spatialBlend = 1.0f;
        impactAudioSource.dopplerLevel = 0.0f;
        impactAudioSource.rolloffMode = AudioRolloffMode.Logarithmic;
        impactAudioSource.maxDistance = 20f;

        rollingAudioSource = gameObject.AddComponent<AudioSource>();
        rollingAudioSource.playOnAwake = false;
        rollingAudioSource.spatialize = true;
        rollingAudioSource.spatialBlend = 1.0f;
        rollingAudioSource.dopplerLevel = 0.0f;
        rollingAudioSource.rolloffMode = AudioRolloffMode.Logarithmic;
        rollingAudioSource.maxDistance = 20f;
        rollingAudioSource.loop = true;

        // Load the Sphere sounds from the Resources folder
        impactAudioSource.clip = Resources.Load<AudioClip>("Impact");
        rollingAudioSource.clip = Resources.Load<AudioClip>("Rolling");
    }

    // Occurs when this object starts colliding with another object
    void OnCollisionEnter(Collision collision)
    {
        // Play an impact sound if the sphere impacts strongly enough.
        if (collision.relativeVelocity.magnitude >= 0.1f)
        {
            impactAudioSource.Play();
        }
    }

    // Occurs each frame that this object continues to collide with another object
    void OnCollisionStay(Collision collision)
    {
        Rigidbody rigid = gameObject.GetComponent<Rigidbody>();

        // Play a rolling sound if the sphere is rolling fast enough.
        if (!rolling && rigid.velocity.magnitude >= 0.01f)
        {
            rolling = true;
            rollingAudioSource.Play();
        }
        // Stop the rolling sound if rolling slows down.
        else if (rolling && rigid.velocity.magnitude < 0.01f)
        {
            rolling = false;
            rollingAudioSource.Stop();
        }
    }

    // Occurs when this object stops colliding with another object
    void OnCollisionExit(Collision collision)
    {
        // Stop the rolling sound if the object falls off and stops colliding.
        if (rolling)
        {
            rolling = false;
            impactAudioSource.Stop();
            rollingAudioSource.Stop();
        }
    }
}
  • Spara skriptet och återgå till Unity.
  • Exportera, skapa och distribuera appen till HoloLens-emulatorn.
  • Använd hörlurar för att få full effekt och gå närmare och längre från scenen för att höra ljuden förändras.

Kapitel 6 – Rumslig mappning

Nu ska vi använda rumslig mappning för att placera spelplanen på ett verkligt objekt i den verkliga världen.

Mål

  • För in din verkliga värld i den virtuella världen.
  • Placera dina hologram där de betyder mest för dig.

Instruktioner

  • Klicka på mappen Hologram på projektpanelen.
  • Dra tillgång till spatial mappning till roten i hierarkin.
  • Klicka på objektet Rumslig mappning i hierarkin.
  • Ändra följande egenskaper på panelen Kontroll:
    • Markera rutan Rita visuella nät .
    • Leta upp Rita material och klicka på cirkeln till höger. Skriv "wireframe" i sökfältet längst upp. Klicka på resultatet och stäng sedan fönstret.
  • Exportera, skapa och distribuera appen till HoloLens-emulatorn.
  • När appen körs renderas ett nät i ett tidigare skannat verkligt vardagsrum i trådram.
  • Titta på hur en rullande sfär kommer att falla av scenen och på golvet!

Nu ska vi visa dig hur du flyttar OrigamiCollection till en ny plats:

  • I mappen Skript skapar du ett skript med namnet TapToPlaceParent.
  • I hierarkin expanderar du OrigamiCollection och väljer stage-objektet .
  • Dra skriptet TapToPlaceParent till stage-objektet.
  • Öppna TapToPlaceParent-skriptet i Visual Studio och uppdatera det så att det blir följande:
using UnityEngine;

public class TapToPlaceParent : MonoBehaviour
{
    bool placing = false;

    // Called by GazeGestureManager when the user performs a Select gesture
    void OnSelect()
    {
        // On each Select gesture, toggle whether the user is in placing mode.
        placing = !placing;

        // If the user is in placing mode, display the spatial mapping mesh.
        if (placing)
        {
            SpatialMapping.Instance.DrawVisualMeshes = true;
        }
        // If the user is not in placing mode, hide the spatial mapping mesh.
        else
        {
            SpatialMapping.Instance.DrawVisualMeshes = false;
        }
    }

    // Update is called once per frame
    void Update()
    {
        // If the user is in placing mode,
        // update the placement to match the user's gaze.

        if (placing)
        {
            // Do a raycast into the world that will only hit the Spatial Mapping mesh.
            var headPosition = Camera.main.transform.position;
            var gazeDirection = Camera.main.transform.forward;

            RaycastHit hitInfo;
            if (Physics.Raycast(headPosition, gazeDirection, out hitInfo,
                30.0f, SpatialMapping.PhysicsRaycastMask))
            {
                // Move this object's parent object to
                // where the raycast hit the Spatial Mapping mesh.
                this.transform.parent.position = hitInfo.point;

                // Rotate this object's parent object to face the user.
                Quaternion toQuat = Camera.main.transform.localRotation;
                toQuat.x = 0;
                toQuat.z = 0;
                this.transform.parent.rotation = toQuat;
            }
        }
    }
}
  • Exportera, skapa och distribuera appen.
  • Nu bör du kunna placera spelet på en specifik plats genom att titta på det med hjälp av gesten Välj (A eller Blanksteg) och sedan flytta till en ny plats och använda gesten Välj igen.

Slutet

Och det är slutet på den här självstudien!

Du har lärt dig att:

  • Så här skapar du en holografisk app i Unity.
  • Hur man använder blick, gest, röst, ljud och rumslig mappning.
  • Så här skapar och distribuerar du en app med Hjälp av Visual Studio.

Nu är du redo att börja skapa egna holografiska appar!

Se även