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

Viktigt

Självstudierna Mixed Reality Academy har utformats med HoloLens (1:a gen), Unity 2017 och Mixed Reality Immersive Headsets i åtanke. Därför anser vi att det är viktigt att lämna de här självstudierna på plats för utvecklare som fortfarande letar efter vägledning i utvecklingen för dessa enheter. De här självstudierna uppdateras inte med de senaste verktygen eller interaktionerna som används för HoloLens 2 och kanske inte är kompatibla med nyare versioner av Unity. De kommer att finnas kvar för att fortsätta arbeta med de enheter som stöds. En ny serie självstudier har publicerats för HoloLens 2.


Den här självstudien vägled dig genom ett komplett projekt, inbyggt i Unity, som visar grundläggande Windows Mixed Reality-funktioner på HoloLens inklusive blick, gester,röstindata, 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

Project filer

  • Ladda ned de filer som krävs av projektet. Kräver Unity 2017.2 eller senare.
    • Om du fortfarande behöver unity 5.6-stöd kan du använda den här versionen.
    • Om du fortfarande behöver unity 5.5-stöd kan du använda den här versionen.
    • Om du fortfarande behöver unity 5.4-stöd kan du använda den här versionen.
  • Ta bort arkivering av filerna till skrivbordet eller någon annan plats som är lätt att nå. Behåll mappnamnet somByte.

Anteckning

Om du vill titta igenom källkoden innan du laddar ned den finns den 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 gjort.

Instruktioner

  • Starta Unity.
  • Välj Öppna.
  • Ange plats som mappen Mapp som du tidigare avarkiverade.
  • Välj Alternativet och klicka på Välj mapp.
  • Spara den nya scenen: File / Save Scene As.
  • Ge scenen namnet Start och tryck på knappen Spara.

Konfigurera huvudkameran

  • I hierarkipanelen väljer du Huvudkamera.
  • I Kontroll anger du dess transformeringsposition till 0,0,0.
  • Leta upp 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 tillMappCollection.
  • Från HologramProject panelen:
    • Dra Stage (Fas) till hierarkin för att bli underordnad TilllLCollection.
    • Dra Sphere1 till hierarkin för att vara underordnad TilldrofCollection.
    • Dra Sphere2 till hierarkin för att vara underordnad TilldrofCollection.
  • Högerklicka på objektet Riktningsbelysning på hierarkipanelen och välj Ta bort.
  • Dra Lights Hologram roten hierarkipanelen från mappen .
  • I hierarkin väljer du Alternativet.
  • I Kontroll 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 Objekt objekt 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 File > Build Inställningar.
  • Välj Windows Store i listan Plattform och klicka på Växla plattform.
  • Ange SDK till Universal 10 och Build Type (Versionstyp) till D3D.
  • Kontrollera Unity C#-projekt.
  • Klicka på Lägg till öppna scener för att lägga till scenen.
  • Klicka på Player Inställningar....
  • I kontrollpanelen väljer du Windows Store-logotypen. Välj sedan Publishing Inställningar.
  • I avsnittet Funktioner väljer du funktionerna Microphone och SpatialPerception.
  • I fönstret Skapa Inställningar klickar du på Skapa.
  • Skapa en ny mapp med namnet "App".
  • Klicka på appmappen.
  • Tryck på Välj mapp.
  • När Unity är klart Utforskaren ett fönster.
  • Öppna mappen App.
  • Öppna Den Visual Studio lösningen.
  • Använd det översta verktygsfältet i Visual Studio ändra målet från Felsök till Version och från ARM till X86.
    • Klicka på pilen bredvid knappen Enhet och välj HoloLens Emulator.
    • Klicka på Felsök - > starta utan felsökning eller tryck på Ctrl + F5.
    • Efter en stund börjar emulatorn med Projekt. Första gången emulatorn startaskan det ta upp till 15 minuter innan emulatorn startas. Stäng den inte när den startar.

Kapitel 2 – Blick

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

Mål

  • Visualisera din blick med en världslåst markör.

Instruktioner

  • Gå tillbaka till ditt Unity-projekt och stäng fönstret Skapa Inställningar om det fortfarande är öppet.
  • Välj mappen Hologram i Project panelen.
  • 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 Project panelen.
  • Klicka på menyn Skapa undermeny.
  • Välj C#-skript.
  • Ge skriptet namnet WorldCursor. Obs! Namnet är ärendekänsligt. Du behöver inte lägga till .cs-tillägget.
  • Välj markörobjektethierarkipanelen.
  • Dra och släpp WorldCursor-skriptet i kontrollpanelen.
  • 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 File > Build Inställningar.
  • Gå tillbaka till Visual Studio som tidigare användes för att distribuera till emulatorn.
  • Välj Läs in alla på nytt när du tillfrågas.
  • Klicka på Felsök - > starta utan felsökning eller tryck på Ctrl + F5.
  • Använd Xbox-styrenheten för att titta runt scenen. Observera hur markören interagerar med formen på objekt.

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 faller genom att aktivera tyngdkraft med hjälp av Unity-fysikmotorn.

Mål

  • Kontrollera hologrammen med gesten Välj.

Instruktioner

Vi börjar med att skapa ett skript som kan identifiera gesten Välj.

  • I mappen Skript skapar du ett skript med namnet GazeGestureManager.
  • Dra skriptet GazeGestureManager till objektet ScriptCollection i hierarkin.
  • Öppna skriptet GazeGestureManager i Visual Studio 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 Objektcollection-objektet i hierarkivyn.
  • Dra skriptet SphereCommands till Sphere1-objektet på panelen Hierarki.
  • Dra skriptet SphereCommands till Sphere2-objektet på panelen Hierarki.
  • Ö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å A-knappen 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: "Reset world" för att returnera de bortrullningade sfärerna till deras ursprungliga plats och "Drop sphere" för att få sfären att faller.

Mål

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

Instruktioner

  • I mappen Skript skapar du ett skript med namnet SpeechManager.
  • Dra SpeechManager-skriptet till Objektcollection-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äser enligt följande:
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äga "Drop Sphere".
  • Säg "Reset World"(Återställ världen) för att ta dem tillbaka till sina inledande positioner.

Kapitel 5 – Rumsligt ljud

I det här kapitlet lägger vi till musik i appen och utlöser sedan 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 > Project Inställningar > Ljud
  • Leta upp inställningen Spatializer Plugin och välj MS HRTF Spatializer.
  • Från mappen Hologram drar du objektet Objekt för objekt som inte är upptaget till Objektet Mappkod i hierarkipanelen.
  • Välj AlternativetCollection och leta reda på komponenten Ljudkälla. Ändra dessa egenskaper:
    • Kontrollera egenskapen Spatialize.
    • Kontrollera Spela upp på Aktiv.
    • Ändra Spatial Blend till 3D genom att dra skjutreglaget hela vägen till höger.
    • Kontrollera loopegenskapen.
    • Expandera 3D Sound Inställningar, och ange 0.1 för Gradler Level.
    • Ange Volume Rolloff (Volymomrullning) till Logarithmic Rolloff (Logaritmic Rolloff).
    • Ange Maximalt avstånd till 20.
  • I mappen Skript skapar du ett skript med namnet Sphere Sphere Spheres.
  • Dra SphereUndan till sphere1- och sphere2-objekten i hierarkin.
  • Open Sphere Sphere Sphere 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 kläder för att få full effekt och gå närmare och längre från fasen för att höra ljuden ä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

  • Ta din verkliga värld till den virtuella världen.
  • Placera dina hologram där de är viktigast för dig.

Instruktioner

  • Klicka på Hologram på Project panelen.
  • Dra tillgången Spatial Mapping (Rumslig mappning) till roten i hierarkin.
  • Klicka på objektet Spatial Mapping i hierarkin.
  • Ändra följande egenskaper i kontrollpanelen:
    • Markera rutan Rita visuella nät.
    • Leta upp Draw Material (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 återges ett nät i ett tidigare skannat verkligt rum i trådramen.
  • Se hur en rullande sfär faller från fasen och på marken!

Nu ska vi visa dig hur du flyttar /

  • I mappen Skript skapar du ett skript med namnet TapToPlaceParent.
  • I hierarkin expanderar du AlternativetCollection och väljer objektet Fas.
  • Dra skriptet TapToPlaceParent till objektet Stage.
  • Öppna skriptet TapToPlaceParent i Visual Studio och uppdatera det till 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 viss plats genom att titta på den, använda 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 du använder blick, gest, röst, ljud och rumslig mappning.
  • Skapa och distribuera en app med hjälp av Visual Studio.

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

Se även