HoloLens (första generationen) och Azure 305: Funktioner och lagring


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. Det kommer att finnas en ny serie självstudier som kommer att publiceras i framtiden som visar hur du utvecklar för HoloLens 2. Det här meddelandet uppdateras med en länk till självstudierna när de publiceras.


slutprodukt - start

I den här kursen får du lära dig hur du skapar och använder Azure Functions och lagrar data med en Azure Storage-resurs i ett mixed reality-program.

Azure Functions är en Microsoft-tjänst som gör det möjligt för utvecklare att köra små delar av kod, "funktioner", i Azure. Detta ger ett sätt att delegera arbete till molnet i stället för ditt lokala program, vilket kan ha många fördelar. Azure Functions stöder flera utvecklingsspråk, inklusive C#, F#, Node.js, Java och PHP. Mer information finns i artikeln Azure Functions.

Azure Storage är en Microsoft-molntjänst som gör det möjligt för utvecklare att lagra data, med försäkringen att den kommer att vara högtillgänglig, säker, hållbar, skalbar och redundant. Det innebär att Microsoft hanterar allt underhåll och kritiska problem åt dig. Mer information finns i Azure Storage-artikeln.

Efter att ha slutfört den här kursen kommer du att ha ett uppslukande headsetprogram för mixad verklighet som kommer att kunna göra följande:

  1. Låt användaren se sig omkring i en scen.
  2. Utlös leken av objekt när användaren tittar på en 3D-knapp.
  3. De skapade objekten väljs av en Azure-funktion.
  4. När varje objekt skapas lagrar programmet objekttypen i en Azure-fil som finns i Azure Storage.
  5. När du läser in en andra gång hämtas Azure File-data och används för att spela upp lekåtgärderna från den tidigare instansen av programmet.

I ditt program är det upp till dig hur du ska integrera resultaten med din design. Den här kursen är utformad för att lära dig hur du integrerar en Azure-tjänst med ditt Unity-projekt. Det är ditt jobb att använda den kunskap du får från den här kursen för att förbättra ditt mixed reality-program.

Stöd för enheter

Kurs HoloLens Integrerande headset
MR och Azure 305: Funktioner och lagring ✔️ ✔️

Anteckning

Den här kursen fokuserar främst på Windows Mixed Reality integrerande (VR) headset, men du kan också använda det du lär dig i den här kursen för att Microsoft HoloLens. När du följer kursen visas anteckningar om eventuella ändringar som du kan behöva använda för att stödja HoloLens.

Förutsättningar

Anteckning

Den här självstudien är utformad för utvecklare som har grundläggande erfarenhet av Unity och C#. Tänk också på att kraven och de skriftliga instruktionerna i det här dokumentet representerar vad som har testats och verifierats i skrivande stund (maj 2018). Du är fri att använda den senaste programvaran, som anges i artikeln installera verktyg , även om det inte bör antas att informationen i den här kursen perfekt matchar vad du hittar i nyare programvara än vad som anges nedan.

Vi rekommenderar följande maskinvara och programvara för den här kursen:

Innan du börjar

För att undvika problem med att skapa det här projektet rekommenderar vi starkt att du skapar projektet som nämns i den här självstudien i en rotmapp eller nära rotmapp (långa mappsökvägar kan orsaka problem vid byggtiden).

Kapitel 1 – Azure-portalen

Om du vill använda Azure Storage-tjänsten måste du skapa och konfigurera ett lagringskonto i Azure Portal.

  1. Logga in på Azure-portalen.

    Anteckning

    Om du inte redan har ett Azure-konto måste du skapa ett. Om du följer den här självstudien i ett klassrum eller en labbsituation ber du instruktören eller någon av rektorerna om hjälp med att konfigurera ditt nya konto.

  2. När du är inloggad klickar du på Nytt i det övre vänstra hörnet och söker efter lagringskonto och klickar på Retur.

    azure storage search

    Anteckning

    Ordet Nytt kan ha ersatts med Skapa en resurs i nyare portaler.

  3. Den nya sidan innehåller en beskrivning av Azure Storage-kontotjänsten . Längst ned till vänster i den här prompten väljer du knappen Skapa för att skapa en association med den här tjänsten.

    skapa tjänst

  4. När du har klickat på Skapa:

    1. Infoga ett namn för ditt konto, tänk på att det här fältet endast accepterar siffror och gemener.

    2. Som Distributionsmodell väljer du Resource Manager.

    3. För Typ av konto väljer du Lagring (generell användning v1).

    4. Fastställa platsen för resursgruppen (om du skapar en ny resursgrupp). Platsen skulle helst finnas i den region där programmet skulle köras. Vissa Azure-tillgångar är bara tillgängliga i vissa regioner.

    5. För Replikering väljer du Read-access-geo-redundant storage (RA-GRS).

    6. För Prestanda väljer du Standard.

    7. Låt säker överföring vara inaktiverad.

    8. Välj en prenumeration.

    9. Välj en resursgrupp eller skapa en ny. En resursgrupp är ett sätt att övervaka, kontrollera åtkomst, etablera och hantera fakturering för en samling Azure-tillgångar. Vi rekommenderar att du behåller alla Azure-tjänster som är associerade med ett enskilt projekt (t.ex. dessa labb) under en gemensam resursgrupp).

      Om du vill läsa mer om Azure-resursgrupper kan du gå till resursgruppsartikeln.

    10. Du måste också bekräfta att du har förstått de villkor som tillämpas på den här tjänsten.

    11. Välj Skapa.

      information om indatatjänsten

  5. När du har klickat på Skapa måste du vänta tills tjänsten har skapats. Det kan ta en minut.

  6. Ett meddelande visas i portalen när tjänstinstansen har skapats.

    nytt meddelande i Azure-portalen

  7. Klicka på meddelandena för att utforska din nya tjänstinstans.

    gå till resurs

  8. Klicka på knappen Gå till resurs i meddelandet för att utforska din nya tjänstinstans. Du kommer till din nya lagringskontotjänstinstans .

    access keys

  9. Klicka på Åtkomstnycklar för att visa slutpunkterna för den här molntjänsten. Använd Anteckningar eller liknande om du vill kopiera en av dina nycklar för användning senare. Observera också värdet för anslutningssträngen , eftersom det kommer att användas i klassen AzureServices , som du skapar senare.

    kopiera anslutningssträng

Kapitel 2 – Konfigurera en Azure-funktion

Nu ska du skriva en Azure-funktion i Azure-tjänsten.

Du kan använda en Azure-funktion för att göra nästan vad som helst som du skulle göra med en klassisk funktion i koden, och skillnaden är att den här funktionen kan nås av alla program som har autentiseringsuppgifter för åtkomst till ditt Azure-konto.

Så här skapar du en Azure-funktion:

  1. Från Azure-portalen klickar du på Nytt i det övre vänstra hörnet och söker efter Funktionsapp och klickar på Retur.

    skapa funktionsapp

    Anteckning

    Ordet Ny kan ha ersatts med Skapa en resurs i nyare portaler.

  2. Den nya sidan innehåller en beskrivning av Azure Function App Service. Längst ned till vänster i den här prompten väljer du knappen Skapa för att skapa en association med den här tjänsten.

    funktionsappsinformation

  3. När du har klickat på Skapa:

    1. Ange ett appnamn. Endast bokstäver och siffror kan användas här (antingen versaler eller gemener tillåts).

    2. Välj önskad prenumeration.

    3. Välj en resursgrupp eller skapa en ny. En resursgrupp är ett sätt att övervaka, kontrollera åtkomst, etablera och hantera fakturering för en samling Azure-tillgångar. Vi rekommenderar att du behåller alla Azure-tjänster som är associerade med ett enda projekt (t.ex. dessa labb) under en gemensam resursgrupp).

      Om du vill läsa mer om Azure-resursgrupper kan du läsa artikeln om resursgrupper.

    4. I den här övningen väljer du Windows som valt operativsystem.

    5. Välj Förbrukningsplan för värdplanen.

    6. Fastställ platsen för resursgruppen (om du skapar en ny resursgrupp). Platsen skulle helst finnas i den region där programmet skulle köras. Vissa Azure-tillgångar är bara tillgängliga i vissa regioner. För optimala prestanda väljer du samma region som lagringskontot.

    7. För Lagring väljer du Använd befintlig. Använd sedan den nedrullningsbara menyn och letar upp ditt tidigare skapade lagringsutrymme.

    8. Låt Application Insights vara avstängt för den här övningen.

      Information om indatafunktionsappen

  4. Klicka på knappen Skapa.

  5. När du har klickat på Skapa måste du vänta tills tjänsten har skapats. Det kan ta en minut.

  6. Ett meddelande visas i portalen när tjänstinstansen har skapats.

    nytt meddelande i Azure-portalen

  7. Klicka på meddelandena för att utforska din nya tjänstinstans.

    gå till resursfunktionsappen

  8. Klicka på knappen Gå till resurs i meddelandet för att utforska din nya tjänstinstans. Du kommer till din nya funktionsapptjänstinstans .

  9. Hovra muspekaren över Functionsinstrumentpanelen för funktionsappen, leta upp den i panelen till vänster och klicka sedan på symbolen + (plus).

    skapa ny funktion

  10. På nästa sida kontrollerar du att Webhook + API har valts och för Välj ett språk väljer du CSharp, eftersom det här är det språk som används för den här självstudien. Klicka slutligen på knappen Skapa den här funktionen .

    välj csharp för webhook

  11. Du bör föras till kodsidan (run.csx), om inte klickar du på den nyligen skapade funktionen i funktionslistan i panelen till vänster.

    öppna ny funktion

  12. Kopiera följande kod till din funktion. Den här funktionen returnerar helt enkelt ett slumpmässigt heltal mellan 0 och 2 när den anropas. Oroa dig inte för den befintliga koden, du kan klistra in över toppen av den.

        using System.Net;
        using System.Threading.Tasks;
    
        public static int Run(CustomObject req, TraceWriter log)
        {
            Random rnd = new Random();
            int randomInt = rnd.Next(0, 3);
            return randomInt;
        }
    
        public class CustomObject
        {
            public String name {get; set;}
        }
    
  13. Välj Spara.

  14. Resultatet bör se ut som på bilden nedan.

  15. Klicka på Hämta funktions-URL och anteckna slutpunkten som visas. Du måste infoga den i klassen AzureServices som du kommer att skapa senare i den här kursen.

    Hämta funktionsslutpunkt

    Infoga funktionsslutpunkt

Kapitel 3 – Konfigurera Unity-projektet

Följande är en typisk konfiguration för utveckling med Mixed Reality och är därför en bra mall för andra projekt.

Konfigurera och testa ditt integrerande headset för mixad verklighet.

Anteckning

Du behöver inga rörelsekontrollanter för den här kursen. Om du behöver hjälp med att konfigurera det integrerande headsetet kan du läsa artikeln om att konfigurera mixad verklighet.

  1. Öppna Unity och klicka på Ny.

    Skapa ett nytt Unity-projekt

  2. Nu måste du ange ett Unity-projektnamn. Infoga MR_Azure_Functions. Kontrollera att projekttypen är inställd på 3D. Ange plats till någonstans som passar dig (kom ihåg att närmare rotkatalogerna är bättre). Klicka sedan på Skapa projekt.

    Ge det nya Unity-projektet ett namn

  3. När Unity är öppet är det värt att kontrollera att standardskriptredigeraren är inställd på Visual Studio. Gå till Redigera>inställningar och gå sedan till Externa verktyg från det nya fönstret. Ändra extern skriptredigerare till Visual Studio 2017. Stäng fönstret Inställningar .

    ange Visual Studio som skriptredigerare

  4. Gå sedan tillInställningar för filbygge> och växla plattformen till Universell Windows-plattform genom att klicka på knappen Växla plattform.

    växla plattform till uwp

  5. Gå till Inställningarförfilbygge> och kontrollera att:

    1. Målenheten är inställd på Valfri enhet.

      För Microsoft HoloLens anger du Målenhet till HoloLens.

    2. Byggtyp är inställd på D3D

    3. SDK är inställt på Senaste installerat

    4. Visual Studio-versionen är inställd på Senaste installerad

    5. Build and Run är inställt på Lokal dator

    6. Spara scenen och lägg till den i bygget.

      1. Gör detta genom att välja Lägg till öppna scener. Ett spara-fönster visas.

        lägga till öppna scener

      2. Skapa en ny mapp för detta och eventuell framtida scen och välj sedan knappen Ny mapp för att skapa en ny mapp och ge den namnet Scener.

        mapp för att skapa scener

      3. Öppna mappen Scener och skriv FunctionsScene i textfältet Filnamn: och tryck sedan på Spara.

        Scen för att spara funktioner

  6. De återstående inställningarna i Build Settings (Bygginställningar) bör vara kvar som standard för tillfället.

    Låt standardinställningarna för kompilering vara kvar

  7. I fönstret Build Settings (Bygginställningar ) klickar du på knappen Spelarinställningar . Då öppnas den relaterade panelen i utrymmet där Inspector finns.

    spelarinställningar i inspector

  8. I den här panelen måste några inställningar verifieras:

    1. På fliken Andra inställningar :

      1. Scripting Runtime-versionen ska vara experimentell (.NET 4.6 Equivalent), vilket utlöser ett behov av att starta om redigeraren.
      2. Skriptserverdelen ska vara .NET
      3. API-kompatibilitetsnivån ska vara .NET 4.6
    2. På fliken Publiceringsinställningar går du till Funktioner och kontrollerar:

      • InternetClient

        ange funktioner

    3. Längre ned på panelen, i XR-inställningar (som finns under Publiceringsinställningar), markerar du Virtual Reality Supported (Virtuell verklighet stöds) och kontrollerar att Windows Mixed Reality SDK har lagts till.

      ange XR-inställningar

  9. Tillbaka i Build SettingsUnity C# Projects är inte längre nedtonat. markera kryssrutan bredvid detta.

    tick c# projects

  10. Stäng fönstret Build Settings (Bygginställningar).

  11. Spara din scen och ditt projekt (FILE>SAVE SCENE/FILE>SAVE PROJECT).

Kapitel 4 – Konfigurera huvudkamera

Viktigt

Om du vill hoppa över Unity Set up-komponenterna i den här kursen och fortsätta direkt till koden kan du ladda ned .unitypackage och importera det till ditt projekt som ett anpassat paket. Detta kommer också att innehålla DLL:er från nästa kapitel. Efter importen fortsätter du från kapitel 7.

  1. hierarkipanelen hittar du ett objekt med namnet Huvudkamera. Det här objektet representerar din "huvudpunkt" när du är "inuti" ditt program.

  2. Med Unity-instrumentpanelen framför dig väljer du Main Camera GameObject. Du kommer att märka att Kontrollpanelen (som vanligtvis finns till höger i instrumentpanelen) visar de olika komponenterna i det GameObject, med Transformering överst, följt av Kamera och några andra komponenter. Du måste återställa transformering av huvudkameran, så att den är korrekt placerad.

  3. Det gör du genom att välja kugghjulsikonen bredvid komponenten Kameratransformering och sedan Återställa.

    återställ transformering

  4. Uppdatera sedan transformeringskomponenten så att den ser ut så här:

Transformera – position

X Y Z
0 1 0

Transformera – rotation

X Y Z
0 0 0

Transformera – skala

X Y Z
1 1 1

ställ in kameratransformering

Kapitel 5 – Konfigurera Unity-scenen

  1. Högerklicka i ett tomt område på hierarkipanelen under 3D-objekt och lägg till ett plan.

    skapa nytt plan

  2. När objektet Plane är markerat ändrar du följande parametrar i Kontrollpanelen:

Transformera – position

X Y Z
0 0 4

Transformera – skala

X Y Z
10 1 10

ange planposition och skala

scenvy över planet

  1. Högerklicka i ett tomt område på hierarkipanelen under 3D-objekt och lägg till en kub.

    1. Byt namn på kuben till GazeButton (med kuben markerad trycker du på F2).

    2. Ändra följande parametrar för transformeringsposition i kontrollpanelen:

      X Y Z
      0 3 5

      ställ in knapptransformering av blick

      bildknappsscenvy

    3. Klicka på listrutan Tagg och klicka på Lägg till tagg för att öppna fönstret Taggar & lager.

      lägg till ny tagg

      välj plus

    4. Välj knappen + (plus) och i fältet Nytt taggnamn anger du GazeButton och trycker på Spara.

      namn ny tagg

    5. Klicka på Objektet GazeButton i hierarkipanelen och tilldela den nyligen skapade GazeButton-taggen i Kontrollpanelen.

      tilldela blickknappen den nya taggen

  2. Högerklicka på GazeButton-objektet i hierarkipanelen och lägg till en tom GameObject (som läggs till som ett underordnat objekt).

  3. Markera det nya objektet och byt namn på det till ShapeSpawnPoint.

    1. Ändra följande parametrar för transformeringsposition i kontrollpanelen:

      X Y Z
      0 -1 0

      uppdatera formlekpunktstransformering

      scenvy för formlekpunkt

  4. Därefter skapar du ett 3D Text-objekt för att ge feedback om Status för Azure-tjänsten.

    Högerklicka på GazeButton på hierarkipanelen igen och lägg till ett 3D-objekt>3D-textobjekt som underordnat objekt.

    skapa ett nytt 3D-textobjekt

  5. Byt namn på 3D Text-objektet till AzureStatusText.

  6. Ändra Objekttransformeringsposition för AzureStatusText enligt följande:

    X Y Z
    0 0 -0,6
  7. Ändra AzureStatusText-objektetTransformera skala enligt följande: | X | Y | Z | | | :---: | :---: | :---: | | 0.1 | 0.1 | 0.1 |

    Anteckning

    Oroa dig inte om det verkar vara off-center, eftersom detta kommer att åtgärdas när nedanstående Text Mesh-komponent uppdateras.

  8. Ändra Text Mesh-komponenten så att den matchar nedanstående:

    ange textnätskomponent

    Tips

    Den valda färgen här är Hex färg: 000000FF, men känn dig fri att välja din egen, bara se till att det är läsbart.

  9. Hierarkipanelens struktur bör nu se ut så här:

    Textnät i hierarkin

  10. Din scen bör nu se ut så här:

    Textnät i scenvyn

Kapitel 6 – Importera Azure Storage för Unity

Du kommer att använda Azure Storage för Unity (som i sig utnyttjar .Net SDK för Azure). Du kan läsa mer om detta i artikeln Azure Storage for Unity.

Det finns för närvarande ett känt problem i Unity som kräver att plugin-program konfigureras om efter importen. De här stegen (4–7 i det här avsnittet) krävs inte längre när felet har lösts.

Om du vill importera SDK:n till ditt eget projekt kontrollerar du att du har laddat ned den senaste .unitypackage från GitHub. Gör sedan följande:

  1. Lägg till .unitypackage-filen i Unity med menyalternativetImportera paket> för tillgångar>anpassat paket.

  2. I rutan Importera Unity-paket som visas kan du välja allt under Plugin Storage>. Avmarkera allt annat eftersom det inte behövs för den här kursen.

    importera till paket

  3. Klicka på knappen Importera för att lägga till objekten i projektet.

  4. Gå till mappen Lagring under Plugin-program i projektvyn och välj endast följande plugin-program:

    • Microsoft.Data.Edm

    • Microsoft.Data.OData

    • Microsoft.WindowsAzure.Storage

    • Newtonsoft.Json

    • System.Spatial

      avmarkera Valfri plattform

  5. När dessa specifika plugin-program har valts avmarkerarduValfri plattform och avmarkerarWSAPlayer och klickar sedan på Tillämpa.

    tillämpa plattforms-DLL:ar

    Anteckning

    Vi markerar att just dessa plugin-program endast ska användas i Unity-redigeraren. Det beror på att det finns olika versioner av samma plugin-program i WSA-mappen som kommer att användas när projektet har exporterats från Unity.

  6. I mappen Storage-plugin väljer du endast:

    • Microsoft.Data.Services.Client

      set don't process for dlls

  7. Markera rutan Bearbeta inte under Plattformsinställningar och klicka på Använd.

    tillämpa ingen bearbetning

    Anteckning

    Vi markerar det här plugin-programmet "Bearbeta inte" eftersom Unity-korrigeringsprogrammet för sammansättning har svårt att bearbeta det här plugin-programmet. Plugin-programmet fungerar fortfarande även om det inte bearbetas.

Kapitel 7 – Skapa klassen AzureServices

Den första klassen som du ska skapa är klassen AzureServices .

Klassen AzureServices ansvarar för:

  • Lagra autentiseringsuppgifter för Azure-konto.

  • Anropa din Azure App-funktion.

  • Uppladdning och nedladdning av datafilen i Azure Cloud Storage.

Så här skapar du den här klassen:

  1. Högerklicka i tillgångsmappen , som finns på projektpanelen, skapa>mapp. Ge mappen namnet Skript.

    skapa ny mapp

    anropsmapp – skript

  2. Dubbelklicka på mappen som nyss skapades för att öppna den.

  3. Högerklicka i mappen Skapa>C#-skript. Anropa skriptet AzureServices.

  4. Dubbelklicka på den nya Klassen AzureServices för att öppna den med Visual Studio.

  5. Lägg till följande namnområden överst i AzureServices:

        using System;
        using System.Threading.Tasks;
        using UnityEngine;
        using Microsoft.WindowsAzure.Storage;
        using Microsoft.WindowsAzure.Storage.File;
        using System.IO;
        using System.Net;
    
  6. Lägg till följande Inspector-fält i klassen AzureServices :

        /// <summary>
        /// Provides Singleton-like behavior to this class.
        /// </summary>
        public static AzureServices instance;
    
        /// <summary>
        /// Reference Target for AzureStatusText Text Mesh object
        /// </summary>
        public TextMesh azureStatusText;
    
  7. Lägg sedan till följande medlemsvariabler i klassen AzureServices :

        /// <summary>
        /// Holds the Azure Function endpoint - Insert your Azure Function
        /// Connection String here.
        /// </summary>
    
        private readonly string azureFunctionEndpoint = "--Insert here you AzureFunction Endpoint--";
    
        /// <summary>
        /// Holds the Storage Connection String - Insert your Azure Storage
        /// Connection String here.
        /// </summary>
        private readonly string storageConnectionString = "--Insert here you AzureStorage Connection String--";
    
        /// <summary>
        /// Name of the Cloud Share - Hosts directories.
        /// </summary>
        private const string fileShare = "fileshare";
    
        /// <summary>
        /// Name of a Directory within the Share
        /// </summary>
        private const string storageDirectory = "storagedirectory";
    
        /// <summary>
        /// The Cloud File
        /// </summary>
        private CloudFile shapeIndexCloudFile;
    
        /// <summary>
        /// The Linked Storage Account
        /// </summary>
        private CloudStorageAccount storageAccount;
    
        /// <summary>
        /// The Cloud Client
        /// </summary>
        private CloudFileClient fileClient;
    
        /// <summary>
        /// The Cloud Share - Hosts Directories
        /// </summary>
        private CloudFileShare share;
    
        /// <summary>
        /// The Directory in the share that will host the Cloud file
        /// </summary>
        private CloudFileDirectory dir;
    

    Viktigt

    Se till att du ersätter slutpunkten och anslutningssträng värden med värdena från Din Azure-lagring som finns i Azure-portalen

  8. Kod för metoderna Awake() och Start() måste nu läggas till. Dessa metoder anropas när klassen initieras:

        private void Awake()
        {
            instance = this;
        }
    
        // Use this for initialization
        private void Start()
        {
            // Set the Status text to loading, whilst attempting connection to Azure.
            azureStatusText.text = "Loading...";
        }
    
        /// <summary>
        /// Call to the Azure Function App to request a Shape.
        /// </summary>
        public async void CallAzureFunctionForNextShape()
        {
    
        }
    

    Viktigt

    Vi fyller i koden för CallAzureFunctionForNextShape() i ett kommande kapitel.

  9. Ta bort metoden Update() eftersom den här klassen inte kommer att använda den.

  10. Spara ändringarna i Visual Studio och gå sedan tillbaka till Unity.

  11. Klicka på och dra klassen AzureServices från mappen Skript till huvudkameraobjektet på hierarkipanelen.

  12. Välj huvudkameran och hämta sedan det underordnade AzureStatusText-objektet under GazeButton-objektet och placera det i referensmålfältet AzureStatusText i Inspector för att ange referensen till AzureServices-skriptet .

    tilldela referensmål för azure-statustext

Kapitel 8 – Skapa klassen ShapeFactory

Nästa skript att skapa är klassen ShapeFactory . Rollen för den här klassen är att skapa en ny form när den begärs och behålla en historik över formerna som skapats i en lista över formhistorik. Varje gång en form skapas uppdateras listan Formhistorik i klassen AzureService och lagras sedan i Azure Storage. Om en lagrad fil hittas i Azure Storage när programmet startas hämtas listan över formhistorik och spelas upp igen, med 3D-textobjektet som anger om den genererade formen kommer från lagring eller ny.

Så här skapar du den här klassen:

  1. Gå till mappen Skript som du skapade tidigare.

  2. Högerklicka i mappen Skapa>C#-skript. Anropa skriptet ShapeFactory.

  3. Dubbelklicka på det nya ShapeFactory-skriptet för att öppna det med Visual Studio.

  4. Se till att klassen ShapeFactory innehåller följande namnområden:

        using System.Collections.Generic;
        using UnityEngine;
    
  5. Lägg till variablerna som visas nedan i klassen ShapeFactory och ersätt funktionerna Start() och Awake() med de nedan:

        /// <summary>
        /// Provide this class Singleton-like behaviour
        /// </summary>
        [HideInInspector]
        public static ShapeFactory instance;
    
        /// <summary>
        /// Provides an Inspector exposed reference to ShapeSpawnPoint
        /// </summary>
        [SerializeField]
        public Transform spawnPoint;
    
        /// <summary>
        /// Shape History Index
        /// </summary>
        [HideInInspector]
        public List<int> shapeHistoryList;
    
        /// <summary>
        /// Shapes Enum for selecting required shape
        /// </summary>
        private enum Shapes { Cube, Sphere, Cylinder }
    
        private void Awake()
        {
            instance = this;
        }
    
        private void Start()
        {
            shapeHistoryList = new List<int>();
        }
    
  6. Metoden CreateShape() genererar de primitiva formerna baserat på den angivna heltalsparametern . Den booleska parametern används för att ange om den form som skapas är från lagring eller ny. Placera följande kod i klassen ShapeFactory under föregående metoder:

        /// <summary>
        /// Use the Shape Enum to spawn a new Primitive object in the scene
        /// </summary>
        /// <param name="shape">Enumerator Number for Shape</param>
        /// <param name="storageShape">Provides whether this is new or old</param>
        internal void CreateShape(int shape, bool storageSpace)
        {
            Shapes primitive = (Shapes)shape;
            GameObject newObject = null;
            string shapeText = storageSpace == true ? "Storage: " : "New: ";
    
            AzureServices.instance.azureStatusText.text = string.Format("{0}{1}", shapeText, primitive.ToString());
    
            switch (primitive)
            {
                case Shapes.Cube:
                newObject = GameObject.CreatePrimitive(PrimitiveType.Cube);
                break;
    
                case Shapes.Sphere:
                newObject = GameObject.CreatePrimitive(PrimitiveType.Sphere);
                break;
    
                case Shapes.Cylinder:
                newObject = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
                break;
            }
    
            if (newObject != null)
            {
                newObject.transform.position = spawnPoint.position;
    
                newObject.transform.localScale = new Vector3(0.5f, 0.5f, 0.5f);
    
                newObject.AddComponent<Rigidbody>().useGravity = true;
    
                newObject.GetComponent<Renderer>().material.color = UnityEngine.Random.ColorHSV(0f, 1f, 1f, 1f, 0.5f, 1f);
            }
        }
    
  7. Se till att spara ändringarna i Visual Studio innan du återgår till Unity.

  8. När du är tillbaka i Unity-redigeraren klickar och drar du klassen ShapeFactory från mappen Skript till huvudkameraobjektethierarkipanelen.

  9. När huvudkameran är markerad ser du att ShapeFactory-skriptkomponenten saknar referensen för Spawn Point . Du kan åtgärda problemet genom att dra ShapeSpawnPoint-objektet från hierarkipanelen till referensmålet för lekpunkt .

    ange referensmål för formfabriken

Kapitel 9 – Skapa klassen Gaze

Det sista skriptet som du behöver skapa är klassen Gaze .

Den här klassen ansvarar för att skapa en Raycast som ska projiceras framåt från huvudkameran för att identifiera vilket objekt användaren tittar på. I det här fallet måste Raycast identifiera om användaren tittar på GazeButton-objektet i scenen och utlöser ett beteende.

Så här skapar du den här klassen:

  1. Gå till mappen Skript som du skapade tidigare.

  2. Högerklicka på projektpanelen och skapa>C#-skript. Anropa skriptet Gaze.

  3. Dubbelklicka på det nya Gaze-skriptet för att öppna det med Visual Studio.

  4. Kontrollera att följande namnområde finns överst i skriptet:

        using UnityEngine;
    
  5. Lägg sedan till följande variabler i klassen Gaze :

        /// <summary>
        /// Provides Singleton-like behavior to this class.
        /// </summary>
        public static Gaze instance;
    
        /// <summary>
        /// The Tag which the Gaze will use to interact with objects. Can also be set in editor.
        /// </summary>
        public string InteractibleTag = "GazeButton";
    
        /// <summary>
        /// The layer which will be detected by the Gaze ('~0' equals everything).
        /// </summary>
        public LayerMask LayerMask = ~0;
    
        /// <summary>
        /// The Max Distance the gaze should travel, if it has not hit anything.
        /// </summary>
        public float GazeMaxDistance = 300;
    
        /// <summary>
        /// The size of the cursor, which will be created.
        /// </summary>
        public Vector3 CursorSize = new Vector3(0.05f, 0.05f, 0.05f);
    
        /// <summary>
        /// The color of the cursor - can be set in editor.
        /// </summary>
        public Color CursorColour = Color.HSVToRGB(0.0223f, 0.7922f, 1.000f);
    
        /// <summary>
        /// Provides when the gaze is ready to start working (based upon whether
        /// Azure connects successfully).
        /// </summary>
        internal bool GazeEnabled = false;
    
        /// <summary>
        /// The currently focused object.
        /// </summary>
        internal GameObject FocusedObject { get; private set; }
    
        /// <summary>
        /// The object which was last focused on.
        /// </summary>
        internal GameObject _oldFocusedObject { get; private set; }
    
        /// <summary>
        /// The info taken from the last hit.
        /// </summary>
        internal RaycastHit HitInfo { get; private set; }
    
        /// <summary>
        /// The cursor object.
        /// </summary>
        internal GameObject Cursor { get; private set; }
    
        /// <summary>
        /// Provides whether the raycast has hit something.
        /// </summary>
        internal bool Hit { get; private set; }
    
        /// <summary>
        /// This will store the position which the ray last hit.
        /// </summary>
        internal Vector3 Position { get; private set; }
    
        /// <summary>
        /// This will store the normal, of the ray from its last hit.
        /// </summary>
        internal Vector3 Normal { get; private set; }
    
        /// <summary>
        /// The start point of the gaze ray cast.
        /// </summary>
        private Vector3 _gazeOrigin;
    
        /// <summary>
        /// The direction in which the gaze should be.
        /// </summary>
        private Vector3 _gazeDirection;
    

Viktigt

Vissa av dessa variabler kommer att kunna redigeras i redigeraren.

  1. Kod för metoderna Awake() och Start() måste nu läggas till.

        /// <summary>
        /// The method used after initialization of the scene, though before Start().
        /// </summary>
        private void Awake()
        {
            // Set this class to behave similar to singleton
            instance = this;
        }
    
        /// <summary>
        /// Start method used upon initialization.
        /// </summary>
        private void Start()
        {
            FocusedObject = null;
            Cursor = CreateCursor();
        }
    
  2. Lägg till följande kod, som skapar ett markörobjekt i början, tillsammans med metoden Update(), som kör Raycast-metoden, tillsammans med att vara där booleskt GazeEnabled-booleskt värde växlas:

        /// <summary>
        /// Method to create a cursor object.
        /// </summary>
        /// <returns></returns>
        private GameObject CreateCursor()
        {
            GameObject newCursor = GameObject.CreatePrimitive(PrimitiveType.Sphere);
            newCursor.SetActive(false);
    
            // Remove the collider, so it doesn't block raycast.
            Destroy(newCursor.GetComponent<SphereCollider>());
            newCursor.transform.localScale = CursorSize;
    
            newCursor.GetComponent<MeshRenderer>().material = new Material(Shader.Find("Diffuse"))
            {
                color = CursorColour
            };
    
            newCursor.name = "Cursor";
    
            newCursor.SetActive(true);
    
            return newCursor;
        }
    
        /// <summary>
        /// Called every frame
        /// </summary>
        private void Update()
        {
            if(GazeEnabled == true)
            {
                _gazeOrigin = Camera.main.transform.position;
    
                _gazeDirection = Camera.main.transform.forward;
    
                UpdateRaycast();
            }
        }
    
  3. Lägg sedan till metoden UpdateRaycast(), som kommer att projicera en Raycast och identifiera träffmålet.

        private void UpdateRaycast()
        {
            // Set the old focused gameobject.
            _oldFocusedObject = FocusedObject;
    
            RaycastHit hitInfo;
    
            // Initialise Raycasting.
            Hit = Physics.Raycast(_gazeOrigin,
                _gazeDirection,
                out hitInfo,
                GazeMaxDistance, LayerMask);
    
            HitInfo = hitInfo;
    
            // Check whether raycast has hit.
            if (Hit == true)
            {
                Position = hitInfo.point;
    
                Normal = hitInfo.normal;
    
                // Check whether the hit has a collider.
                if (hitInfo.collider != null)
                {
                    // Set the focused object with what the user just looked at.
                    FocusedObject = hitInfo.collider.gameObject;
                }
                else
                {
                    // Object looked on is not valid, set focused gameobject to null.
                    FocusedObject = null;
                }
            }
            else
            {
                // No object looked upon, set focused gameobject to null.
                FocusedObject = null;
    
                // Provide default position for cursor.
                Position = _gazeOrigin + (_gazeDirection * GazeMaxDistance);
    
                // Provide a default normal.
                Normal = _gazeDirection;
            }
    
            // Lerp the cursor to the given position, which helps to stabilize the gaze.
            Cursor.transform.position = Vector3.Lerp(Cursor.transform.position, Position, 0.6f);
    
            // Check whether the previous focused object is this same 
            //    object. If so, reset the focused object.
            if (FocusedObject != _oldFocusedObject)
            {
                ResetFocusedObject();
    
                if (FocusedObject != null)
                {
                if (FocusedObject.CompareTag(InteractibleTag.ToString()))
                {
                        // Set the Focused object to green - success!
                        FocusedObject.GetComponent<Renderer>().material.color = Color.green;
    
                        // Start the Azure Function, to provide the next shape!
                        AzureServices.instance.CallAzureFunctionForNextShape();
                    }
                }
            }
        }
    
  4. Slutligen lägger du till metoden ResetFocusedObject(), som växlar den aktuella färgen för GazeButton-objekten, som anger om den skapar en ny form eller inte.

        /// <summary>
        /// Reset the old focused object, stop the gaze timer, and send data if it
        /// is greater than one.
        /// </summary>
        private void ResetFocusedObject()
        {
            // Ensure the old focused object is not null.
            if (_oldFocusedObject != null)
            {
                if (_oldFocusedObject.CompareTag(InteractibleTag.ToString()))
                {
                    // Set the old focused object to red - its original state.
                    _oldFocusedObject.GetComponent<Renderer>().material.color = Color.red;
                }
            }
        }
    
  5. Spara ändringarna i Visual Studio innan du återgår till Unity.

  6. Klicka och dra klassen Gaze från mappen Skript till huvudkameraobjektethierarkipanelen.

Kapitel 10 – Slutföra klassen AzureServices

Med de andra skripten på plats är det nu möjligt att slutföra klassen AzureServices . Detta kommer att uppnås genom att:

  1. Lägga till en ny metod med namnet CreateCloudIdentityAsync(), för att konfigurera de autentiseringsvariabler som behövs för att kommunicera med Azure.

    Den här metoden kontrollerar också om det finns en tidigare lagrad fil som innehåller formlistan.

    Om filen hittas inaktiverar den användaren Gaze och utlöser skapandet av form enligt mönstret för former som lagras i Azure Storage-filen. Användaren kan se detta eftersom textnätet visar "Storage" eller "New", beroende på formernas ursprung.

    Om ingen fil hittas aktiveras Gaze så att användaren kan skapa former när de tittar på GazeButton-objektet i scenen.

        /// <summary>
        /// Create the references necessary to log into Azure
        /// </summary>
        private async void CreateCloudIdentityAsync()
        {
            // Retrieve storage account information from connection string
            storageAccount = CloudStorageAccount.Parse(storageConnectionString);
    
            // Create a file client for interacting with the file service.
            fileClient = storageAccount.CreateCloudFileClient();
    
            // Create a share for organizing files and directories within the storage account.
            share = fileClient.GetShareReference(fileShare);
    
            await share.CreateIfNotExistsAsync();
    
            // Get a reference to the root directory of the share.
            CloudFileDirectory root = share.GetRootDirectoryReference();
    
            // Create a directory under the root directory
            dir = root.GetDirectoryReference(storageDirectory);
    
            await dir.CreateIfNotExistsAsync();
    
            //Check if the there is a stored text file containing the list
            shapeIndexCloudFile = dir.GetFileReference("TextShapeFile");
    
            if (!await shapeIndexCloudFile.ExistsAsync())
            {
                // File not found, enable gaze for shapes creation
                Gaze.instance.GazeEnabled = true;
    
                azureStatusText.text = "No Shape\nFile!";
            }
            else
            {
                // The file has been found, disable gaze and get the list from the file
                Gaze.instance.GazeEnabled = false;
    
                azureStatusText.text = "Shape File\nFound!";
    
                await ReplicateListFromAzureAsync();
            }
        }
    
  2. Nästa kodfragment kommer från metoden Start(). där ett anrop görs till metoden CreateCloudIdentityAsync(). Kopiera gärna över din aktuella Start() -metod med följande:

        private void Start()
        {
            // Disable TLS cert checks only while in Unity Editor (until Unity adds support for TLS)
    #if UNITY_EDITOR
            ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
    #endif
    
            // Set the Status text to loading, whilst attempting connection to Azure.
            azureStatusText.text = "Loading...";
    
            //Creating the references necessary to log into Azure and check if the Storage Directory is empty
            CreateCloudIdentityAsync();
        }
    
  3. Fyll i koden för metoden CallAzureFunctionForNextShape(). Du kommer att använda den tidigare skapade Azure-funktionsappen för att begära ett formindex. När den nya formen har tagits emot skickar den här metoden formen till klassen ShapeFactory för att skapa den nya formen i scenen. Använd koden nedan för att slutföra brödtexten i CallAzureFunctionForNextShape().

        /// <summary>
        /// Call to the Azure Function App to request a Shape.
        /// </summary>
        public async void CallAzureFunctionForNextShape()
        {
            int azureRandomInt = 0;
    
            // Call Azure function
            HttpWebRequest webRequest = WebRequest.CreateHttp(azureFunctionEndpoint);
    
            WebResponse response = await webRequest.GetResponseAsync();
    
            // Read response as string
            using (Stream stream = response.GetResponseStream())
            {
                StreamReader reader = new StreamReader(stream);
    
                String responseString = reader.ReadToEnd();
    
                //parse result as integer
                Int32.TryParse(responseString, out azureRandomInt);
            }
    
            //add random int from Azure to the ShapeIndexList
            ShapeFactory.instance.shapeHistoryList.Add(azureRandomInt);
    
            ShapeFactory.instance.CreateShape(azureRandomInt, false);
    
            //Save to Azure storage
            await UploadListToAzureAsync();
        }
    
  4. Lägg till en metod för att skapa en sträng genom att sammanfoga heltalen som lagras i listan över formhistorik och spara den i din Azure Storage-fil.

        /// <summary>
        /// Upload the locally stored List to Azure
        /// </summary>
        private async Task UploadListToAzureAsync()
        {
            // Uploading a local file to the directory created above
            string listToString = string.Join(",", ShapeFactory.instance.shapeHistoryList.ToArray());
    
            await shapeIndexCloudFile.UploadTextAsync(listToString);
        }
    
  5. Lägg till en metod för att hämta texten som lagras i filen som finns i Azure Storage-filen och deserialisera den i en lista.

  6. När den här processen är klar återaktiveras blicken med metoden så att användaren kan lägga till fler former i scenen.

        ///<summary>
        /// Get the List stored in Azure and use the data retrieved to replicate 
        /// a Shape creation pattern
        ///</summary>
        private async Task ReplicateListFromAzureAsync()
        {
            string azureTextFileContent = await shapeIndexCloudFile.DownloadTextAsync();
    
            string[] shapes = azureTextFileContent.Split(new char[] { ',' });
    
            foreach (string shape in shapes)
            {
                int i;
    
                Int32.TryParse(shape.ToString(), out i);
    
                ShapeFactory.instance.shapeHistoryList.Add(i);
    
                ShapeFactory.instance.CreateShape(i, true);
    
                await Task.Delay(500);
            }
    
            Gaze.instance.GazeEnabled = true;
    
            azureStatusText.text = "Load Complete!";
        }
    
  7. Spara ändringarna i Visual Studio innan du återgår till Unity.

Kapitel 11 – Skapa UWP-lösningen

Så här påbörjar du byggprocessen:

  1. Gå till Inställningarförfilbygge>.

    skapa appen

  2. Klicka på Skapa. Unity startar ett Utforskaren fönster där du behöver skapa och väljer sedan en mapp som appen ska byggas in i. Skapa mappen nu och ge den namnet App. Tryck sedan påVälj mapp när appmappen är markerad.

  3. Unity börjar skapa projektet i mappen App .

  4. När Unity har byggt klart (det kan ta lite tid) öppnas ett Utforskaren fönster på platsen för bygget (kontrollera aktivitetsfältet eftersom det kanske inte alltid visas ovanför fönstren, men meddelar dig om att ett nytt fönster har lagts till).

Kapitel 12 – Distribuera ditt program

Så här distribuerar du programmet:

  1. Gå till mappen App som skapades i det senaste kapitlet. Du ser en fil med namnet på dina appar med tillägget ".sln", som du bör dubbelklicka på, så att den öppnas i Visual Studio.

  2. I Lösningsplattform väljer du x86, Lokal dator.

  3. I Lösningskonfiguration väljer du Felsök.

    För Microsoft HoloLens kan det vara lättare att ställa in detta på Fjärrdator, så att du inte är bunden till datorn. Men du måste också göra följande:

    • Känna till IP-adressen för dina HoloLens, som finns i inställningsnätverket>&>Internet Avancerade alternativ förWi-Fi>. IPv4 är den adress som du bör använda.
    • Se till att utvecklarläget är ; finns i Inställningar>Uppdatera & Säkerhet>för utvecklare.

    distribuera lösning

  4. Gå till menyn Skapa och klicka på Distribuera lösning för att läsa in programmet separat på datorn.

  5. Din app bör nu visas i listan över installerade appar, redo att startas och testas!

Det färdiga Azure Functions- och lagringsprogrammet

Grattis! Du har skapat en mixed reality-app som utnyttjar både Azure Functions- och Azure Storage-tjänsterna. Din app kommer att kunna dra nytta av lagrade data och tillhandahålla en åtgärd baserat på dessa data.

slutprodukt - slut

Bonusövningar

Övning 1

Skapa en andra spawn-punkt och -post som ett objekt skapades från. När du läser in datafilen spelar du upp formerna som skapas från den plats där de ursprungligen skapades.

Övning 2

Skapa ett sätt att starta om appen i stället för att behöva öppna den igen varje gång. Det är bra att börja läsa in scener. När du har gjort det skapar du ett sätt att rensa den lagrade listan i Azure Storage så att den enkelt kan återställas från din app.