Dela via


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


Kommentar

Självstudierna för Mixed Reality Academy har utformats med HoloLens (första generationen) och Mixed Reality Immersive Headsets 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 med 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 de 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å koddelar, "functions", 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 om 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 Artikeln om Azure Storage.

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 titta runt i en scen.
  2. Utlös spawning 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 Uppslukande headset
MR och Azure 305: Funktioner och lagring ✔️ ✔️

Kommentar

Den här kursen fokuserar främst på Windows Mixed Reality-headset (VR) men du kan även använda det du lär dig i den här kursen för 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

Kommentar

Den här självstudien är utformad för utvecklare som har grundläggande erfarenhet av Unity och C#. Tänk också på att förutsättningarna och de skriftliga instruktionerna i det här dokumentet representerar det 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 , men det bör inte 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 byggtid).

Kapitel 1 – Azure Portal

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

  1. Logga in på Azure Portal.

    Kommentar

    Om du inte redan har ett Azure-konto måste du skapa ett. Om du följer den här självstudien i en klassrums- eller labbsituation ber du din instruktör 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-sökning

    Kommentar

    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 Resurshanterare.

    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 vara 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 enda projekt (t.ex. dessa labb) under en gemensam resursgrupp).

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

    10. Du måste också bekräfta att du har förstått de villkor som gäller för 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 att tas 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 för att kopiera en av dina nycklar för användning senare. Observera också värdet anslutningssträng , eftersom det kommer att användas i klassen AzureServices , som du kommer att skapa senare.

    kopiera niska veze

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 att komma åt 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

    Kommentar

    Ordet Nytt 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 gå till resursgruppens artikel.

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

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

    6. Fastställa platsen för resursgruppen (om du skapar en ny resursgrupp). Platsen skulle helst vara 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 och använder sedan den nedrullningsbara menyn och letar upp ditt tidigare skapade lagringsutrymme.

    8. Låt Application Insights vara inaktiverat 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 att tas till din nya Funktion App Service-instans.

  9. På instrumentpanelen för funktionsappen hovrar du musen över Functions, finns i panelen till vänster och klickar 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 webbhook

  11. Du bör tas till kodsidan (run.csx), om inte, klicka på den nyligen skapade funktionen i listan Funktioner 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 det anropas. Oroa dig inte för den befintliga koden. Klistra gärna in överst på 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 bilden nedan.

  15. Klicka på Hämta funktions-URL och anteckna slutpunkten som visas. Du måste infoga den i klassen AzureServices som du skapar 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.

Kommentar

Du behöver inte motionskontrollanter för den här kursen. Om du behöver stöd för att konfigurera det uppslukande headsetet kan du läsa artikeln om mixad verklighet.

  1. Öppna Unity och klicka på Nytt.

    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 platsen till någonstans som passar dig (kom ihåg att närmare rotkataloger är bättre). Klicka sedan på Skapa projekt.

    Ge nytt Unity-projekt 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 till Inställningar för filbygge>och växla plattformen till Universal Windows Platform genom att klicka på knappen Växla plattform.

    växla plattform till uwp

  5. Gå till Inställningar för filbygge>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 eventuella framtida scenarier, välj sedan knappen Ny mapp , för att skapa en ny mapp, ge den namnet Scener.

        skapa scener-mapp

      3. Öppna den nyligen skapade mappen Scener och skriv FunctionsScene i fältet Filnamn: text och tryck sedan på Spara.

        Spara funktionsscen

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

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

  7. I fönstret Bygginställningar klickar du på knappen Spelarinställningar. Då öppnas den relaterade panelen i det utrymme där inspektören finns.

    spelarinställningar i inspektören

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

    1. På fliken Andra inställningar :

      1. Skriptkörningsversionen bör vara experimentell (.NET 4.6-motsvarighet), 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 (Virtual Reality Supported) och kontrollerar att Windows Mixed Reality SDK har lagts till.

      ange XR-inställningar

  9. Tillbaka i Bygginställningar Unity C#-projekt är inte längre nedtonade. Markera kryssrutan bredvid detta.

    tick c# projects

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

  11. Spara scen och 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 den till projektet 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. I hierarkipanelen hittar du ett objekt med namnet Main Camera. 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 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 kamerans transformeringskomponent och välja Återställ.

    å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

ange 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 planets position och skala

scenvy av 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

      set gaze button transform

      bildknappsscenvy

    3. Klicka på listrutan Tagga och klicka på Lägg till tagg för att öppna fönstret Taggar och 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. Välj 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 i hierarkipanelen igen och lägg till ett 3D-objekts>3D-textobjekt som underordnat objekt.

    skapa nytt 3D-textobjekt

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

  6. Ändra AzureStatusText-objektets transformeringsposition enligt följande:

    X Y Z
    0 0 -0.6
  7. Ändra AzureStatusText-objektets transformeringsskala enligt följande: | X | Y | Z | | :---: | :---: | :---: | | 0,1 | 0,1 | 0,1 |

    Kommentar

    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 textnätkomponenten så att den matchar nedanstående:

    ange textnätkomponent

    Dricks

    Den valda färgen här är Hex färg: 000000FF, men gärna välja din egen, se bara till att den är läsbar.

  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 for Unity (som själv 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 åtgärdats.

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 menyalternativet Importera paket>för tillgångar.>

  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 avmarkerar du Valfri plattform och avmarkerar WSAPlayer och klickar sedan på Använd.

    tillämpa plattforms-DLL:ar

    Kommentar

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

  6. I mappen Storage-plugin-program 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

    Kommentar

    Vi markerar plugin-programmet "Bearbeta inte" eftersom Unity-sammansättningskorrigeringen har svårt att bearbeta 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 i projektpanelen, Skapa>mapp. Ge mappen namnet Skript.

    skapa ny mapp

    samtalsmapp – 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 Kontrollfä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 niska veze värden med värdena från azure-lagringen 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 initierar:

        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 framtida kapitel.

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

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

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

  12. Välj huvudkameran och ta sedan det underordnade AzureStatusText-objektet under GazeButton-objektet och placera det i fältet AzureStatusText-referensmål 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 formhistoriklista. 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 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. Kontrollera 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 följande:

        /// <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 skapats för närvarande är från lagring eller ny. Placera följande kod i klassen ShapeFactory under de tidigare metoderna:

        /// <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 återvänder till Unity.

  8. Tillbaka i Unity-redigeraren klickar och drar du klassen ShapeFactory från mappen Skript till huvudkameraobjektet i hierarkipanelen.

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

    ange referensmål för formfabrik

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 kommer att 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 i projektpanelen, 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 kan 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 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 projicerar en Raycast och identifierar 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 gazebutton-objektens aktuella färg, vilket 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 återvänder till Unity.

  6. Klicka och dra klassen Gaze från mappen Skript till huvudkameraobjektet i hierarkipanelen.

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 kommunikation 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 formernas mönster, 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 aktiverar den Gaze, vilket gör 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 görs ett anrop 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 använder 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 formhistoriklistan och spara den i Azure Storage-filen.

        /// <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 aktiverar metoden blicken igen 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 återvänder till Unity.

Kapitel 11 – Skapa UWP-lösningen

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

  1. Gå till Inställningar för filbygge>.

    skapa appen

  2. Klicka på Skapa. Unity startar ett Istraživač datoteka 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 med appmappen markerad.

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

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

Kapitel 12 – Distribuera ditt program

Så här distribuerar du ditt program:

  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 du kan öppna den 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 enklare att ställa in detta på Fjärrdator, så att du inte är ansluten till datorn. Men du måste också göra följande:

    • Känna till IP-adressen för dina HoloLens, som finns i Inställningar>Nätverk och Internet>Wi-Fi>Avancerade alternativ. IPv4 är den adress som du bör använda.
    • Se till att utvecklarläget är på; finns i Inställningar>Uppdatera och säkerhet>för utvecklare.

    distribuera lösning

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

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

Ditt färdiga Azure Functions- och Storage-program

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 -end

Bonusövningar

Övning 1

Skapa en andra spawn-punkt och -post som spawn-punkten 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.