Grunderna i HoloLens (första generationen) 101: Slutför projektet med enheten


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 101: Slutför projektet med enheten ✔️

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.
  • Eftersom Projektet Datacenter inte innehåller någon scen sparar du den tomma standardscenen i en ny fil med hjälp av: Spara / scen som.
  • Ge den nya scenen namnet Origami och tryck på knappen Spara .

Konfigurera den virtuella 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 Hologram på projektpanelen (expandera Tillgångar och välj Hologram eller dubbelklicka på mappen Hologram på projektpanelen):
    • 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 Universell Windows-plattform 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å Skapa.

  • I utforskarfönstret som visas skapar du 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 (dubbelklicka på) Origami.sln.

  • 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 Fjärrdator att distribuera via Wi-Fi.

    • Ange Namnet eller IP-adressen för din HoloLens som Adress . Om du inte känner till enhetens IP-adress kan du titta i Inställningar > Nätverk & Avancerade internetalternativ > eller fråga Cortana "Hej Cortana, Vad är min IP-adress?"
    • Om HoloLens är ansluten via USB kan du i stället välja Enhet att distribuera via USB.
    • Låt autentiseringsläget vara inställt på Universell.
    • Klicka på Välj
  • Klicka på Felsök > start utan felsökning eller tryck på Ctrl + F5. Om det här är första gången du distribuerar till din enhet måste du koppla den till Visual Studio.

  • Projektet Origami kommer nu att byggas, distribueras till holoLens och sedan köras.

  • Sätt på dig HoloLens och se dig omkring för att se dina nya hologram.

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 the cursor 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 holoLens.
  • 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.
  • Titta nu runt scenen och lägg märke till 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 och kan sedan identifiera gesten Välj.

  • 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 Awake()
    {
        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.
  • Titta på en av sfärerna.
  • Utför markeringsgesten och watch sfärens släpp på ytan nedan.

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.
  • Titta 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
  • I kontrollpanelen till höger letar du upp plugin-inställningen Spatializer och väljer MS HRTF Spatializer.
  • Dra objektet Ambience till objektet OrigamiCollection i hierarkipanelen från mappen Holograms på projektpanelen.
  • Välj OrigamiCollection och leta reda på komponenten Ljudkälla på panelen Inspector. Ä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. Värdet ska ändras från 0 till 1 när du flyttar skjutreglaget.
    • 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 och släpp 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.
  • Gå närmare och längre från scenen och vänd sida till sida 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

  • I Unity klickar du 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. När du gör detta bör värdet för Draw Material anges till Wireframe.
  • Exportera, skapa och distribuera appen till HoloLens.
  • När appen körs överläggs din verkliga värld av ett trådramsnät.
  • 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 nu kunna placera spelet på en specifik plats genom att titta på det, använda gesten Välj och sedan flytta till en ny plats och använda gesten Välj igen.

Kapitel 7 - Holografisk kul

Mål

  • Avslöja ingången till en holografisk undre värld.

Instruktioner

Nu ska vi visa dig hur du avslöjar den holografiska underjorden:

  • Från mappen Hologram på projektpanelen:
    • Dra Underworld till hierarkin för att vara underordnad OrigamiCollection.
  • Skapa ett skript med namnet HitTarget i mappen Skript.
  • I hierarkin expanderar du OrigamiCollection.
  • Expandera stage-objektet och välj målobjektet (blå fläkt).
  • Dra HitTarget-skriptet till målobjektet .
  • Öppna HitTarget-skriptet i Visual Studio och uppdatera det så att det blir följande:
using UnityEngine;

public class HitTarget : MonoBehaviour
{
    // These public fields become settable properties in the Unity editor.
    public GameObject underworld;
    public GameObject objectToHide;

    // Occurs when this object starts colliding with another object
    void OnCollisionEnter(Collision collision)
    {
        // Hide the stage and show the underworld.
        objectToHide.SetActive(false);
        underworld.SetActive(true);

        // Disable Spatial Mapping to let the spheres enter the underworld.
        SpatialMapping.Instance.MappingEnabled = false;
    }
}
  • I Unity väljer du målobjektet .
  • Två offentliga egenskaper visas nu i hit target-komponenten och behöver referera till objekt i vår scen:
    • Dra Underworld från panelen Hierarki till underjordsegenskapen på hit target-komponenten.
    • Dra Scenen från hierarkipanelen till egenskapen Object to Hide (Objekt) för att dölja för hit target-komponenten .
  • Exportera, skapa och distribuera appen.
  • Placera Origami-samlingen på golvet och använd sedan gesten Välj för att få en sfär att falla.
  • När sfären träffar målet (blå fläkt) inträffar en explosion. Samlingen kommer att döljas och ett hål till underjorden visas.

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 din egen holografiska upplevelse!

Se även