HoloLens (1e generatie) en Azure 305: Functies en opslag


Notitie

De Mixed Reality Academy-zelfstudies zijn ontworpen met HoloLens (1e generatie) en Mixed Reality Immersive Headsets in gedachten. Daarom vinden we het belangrijk om deze zelfstudies te laten staan voor ontwikkelaars die nog steeds op zoek zijn naar richtlijnen bij het ontwikkelen van deze apparaten. Deze zelfstudies worden niet bijgewerkt met de meest recente toolsets of interacties die worden gebruikt voor HoloLens 2. Ze worden onderhouden om te blijven werken op de ondersteunde apparaten. Er komt een nieuwe reeks zelfstudies die in de toekomst zullen worden gepubliceerd, waarin wordt gedemonstreerd hoe u kunt ontwikkelen voor HoloLens 2. Deze kennisgeving wordt bijgewerkt met een koppeling naar deze zelfstudies wanneer ze worden gepost.


eindproduct -start

In deze cursus leert u hoe u Azure Functions maakt en gebruikt en gegevens opslaat met een Azure Storage-resource in een mixed reality-toepassing.

Azure Functions is een Microsoft-service, waarmee ontwikkelaars kleine stukjes code, 'functions', in Azure kunnen uitvoeren. Dit biedt een manier om werk naar de cloud te delegeren in plaats van naar uw lokale toepassing, wat veel voordelen kan hebben. Azure Functions ondersteunt verschillende ontwikkeltalen, waaronder C#, F#, Node.js, Java en PHP. Raadpleeg het artikel Azure Functions voor meer informatie.

Azure Storage is een Microsoft-cloudservice, waarmee ontwikkelaars gegevens kunnen opslaan, met de verzekering dat deze maximaal beschikbaar, veilig, duurzaam, schaalbaar en redundant zijn. Dit betekent dat Microsoft al het onderhoud en kritieke problemen voor u afhandelt. Ga naar het artikel Azure Storage voor meer informatie.

Nadat u deze cursus hebt voltooid, hebt u een mixed reality immersive headset-toepassing die het volgende kan doen:

  1. Sta de gebruiker toe om rond een scène te staren.
  2. Activeer de spawning van objecten wanneer de gebruiker naar een 3D'-knop staart.
  3. De voortgebrachte objecten worden gekozen door een Azure-functie.
  4. Wanneer elk object wordt gegenereerd, slaat de toepassing het objecttype op in een Azure-bestand, dat zich in Azure Storage bevindt.
  5. Bij een tweede keer laden worden de Azure File-gegevens opgehaald en gebruikt om de spawning-acties uit het vorige exemplaar van de toepassing opnieuw af te spelen.

In uw toepassing is het aan u om te bepalen hoe u de resultaten integreert met uw ontwerp. In deze cursus leert u hoe u een Azure-service integreert met uw Unity-project. Het is uw taak om de kennis die u op doet uit deze cursus te gebruiken om uw mixed reality-toepassing te verbeteren.

Ondersteuning voor apparaten

Cursus HoloLens Immersive headsets
MR en Azure 305: Functies en opslag ✔️ ✔️

Notitie

Hoewel deze cursus zich voornamelijk richt op Windows Mixed Reality immersive (VR) headsets, kunt u wat u in deze cursus leert ook toepassen op Microsoft HoloLens. Terwijl u de cursus volgt, ziet u notities over alle wijzigingen die u mogelijk moet toepassen om HoloLens te ondersteunen.

Vereisten

Notitie

Deze zelfstudie is bedoeld voor ontwikkelaars die basiservaring hebben met Unity en C#. Houd er ook rekening mee dat de vereisten en schriftelijke instructies in dit document overeenkomen met wat is getest en geverifieerd op het moment van schrijven (mei 2018). U bent vrij om de nieuwste software te gebruiken, zoals vermeld in het artikel over het installeren van de hulpprogramma's , hoewel niet mag worden aangenomen dat de informatie in deze cursus perfect overeenkomt met wat u in nieuwere software vindt dan wat hieronder wordt vermeld.

Voor deze cursus raden we de volgende hardware en software aan:

Voordat u begint

Om problemen met het bouwen van dit project te voorkomen, wordt u sterk aangeraden het project dat in deze zelfstudie wordt genoemd, te maken in een hoofdmap of een bijna-hoofdmap (lange mappaden kunnen problemen veroorzaken tijdens het bouwen).

Hoofdstuk 1: De Azure-portal

Als u de Azure Storage-service wilt gebruiken, moet u een opslagaccount maken en configureren in de Azure Portal.

  1. Meld u aan bij Azure Portal.

    Notitie

    Als u nog geen Azure-account hebt, moet u er een maken. Als u deze zelfstudie volgt in een leslokaal- of labsituatie, vraagt u uw docent of een van de proctors om hulp bij het instellen van uw nieuwe account.

  2. Zodra u bent aangemeld, klikt u op Nieuw in de linkerbovenhoek, zoekt u naar Opslagaccount en klikt u op Enter.

    zoeken in Azure Storage

    Notitie

    Het woord Nieuw is mogelijk vervangen door Een resource maken in nieuwere portals.

  3. De nieuwe pagina bevat een beschrijving van de Azure Storage-accountservice . Selecteer linksonder in deze prompt de knop Maken om een koppeling met deze service te maken.

    service maken

  4. Nadat u op Maken hebt geklikt:

    1. Voeg een naam in voor uw account. Houd er rekening mee dat dit veld alleen cijfers en kleine letters accepteert.

    2. Bij Implementatiemodel selecteert u Resource Manager.

    3. Selecteer bij Soort accountde optie Opslag (algemeen gebruik v1).

    4. Bepaal de locatie voor uw resourcegroep (als u een nieuwe resourcegroep maakt). De locatie bevindt zich idealiter in de regio waar de toepassing wordt uitgevoerd. Sommige Azure-assets zijn alleen beschikbaar in bepaalde regio's.

    5. Bij Replicatie selecteert u Geografisch redundante opslag met leestoegang (RA-GRS).

    6. Selecteer bij Prestaties de optie Standaard.

    7. Laat Veilige overdracht vereist staan op Uitgeschakeld.

    8. Selecteer een Abonnement.

    9. Kies een resourcegroep of maak een nieuwe. Een resourcegroep biedt een manier om een verzameling Azure-assets te bewaken, toegang te beheren, facturering in te richten en te beheren. Het wordt aanbevolen om alle Azure-services die zijn gekoppeld aan één project (zoals deze labs) onder een gemeenschappelijke resourcegroep te houden.

      Als u meer wilt lezen over Azure-resourcegroepen, gaat u naar het artikel over resourcegroepen.

    10. U moet ook bevestigen dat u de voorwaarden hebt begrepen die van toepassing zijn op deze Service.

    11. Selecteer Maken.

      invoerservicegegevens

  5. Nadat u op Maken hebt geklikt, moet u wachten tot de service is gemaakt. Dit kan een minuut duren.

  6. Er wordt een melding weergegeven in de portal zodra het service-exemplaar is gemaakt.

    nieuwe melding in Azure Portal

  7. Klik op de meldingen om uw nieuwe service-exemplaar te verkennen.

    ga naar resource

  8. Klik op de knop Ga naar resource in de melding om uw nieuwe service-exemplaar te verkennen. U wordt naar het nieuwe service-exemplaar van uw opslagaccount gebracht.

    toegangssleutels

  9. Klik op Toegangssleutels om de eindpunten voor deze cloudservice weer te geven. Gebruik Kladblok of iets dergelijks om een van uw sleutels te kopiëren voor later gebruik. Let ook op de waarde van de verbindingsreeks , omdat deze wordt gebruikt in de klasse AzureServices , die u later gaat maken.

    verbindingsreeks kopiëren

Hoofdstuk 2: Een Azure-functie instellen

U gaat nu een Azure-functie schrijven in de Azure-service.

U kunt een Azure-functie gebruiken om bijna alles te doen wat u zou doen met een klassieke functie in uw code. Het verschil is dat deze functie toegankelijk is voor elke toepassing die referenties heeft voor toegang tot uw Azure-account.

Een Azure-functie maken:

  1. Klik in Azure Portal op Nieuw in de linkerbovenhoek, zoek naar Functie-app en klik op Enter.

    functie-app maken

    Notitie

    Het woord Nieuw is mogelijk vervangen door Een resource maken in nieuwere portals.

  2. De nieuwe pagina bevat een beschrijving van de Azure Function App Service. Selecteer linksonder in deze prompt de knop Maken om een koppeling met deze service te maken.

    functie-app-informatie

  3. Nadat u op Maken hebt geklikt:

    1. Geef een app-naam op. Alleen letters en cijfers kunnen hier worden gebruikt (hoofdletters of kleine letters zijn toegestaan).

    2. Selecteer het gewenste abonnement.

    3. Kies een resourcegroep of maak een nieuwe. Een resourcegroep biedt een manier om een verzameling Azure-assets te bewaken, toegang te beheren, facturering in te richten en te beheren. Het wordt aanbevolen om alle Azure-services die zijn gekoppeld aan één project (zoals deze labs) onder een gemeenschappelijke resourcegroep te houden.

      Als u meer wilt lezen over Azure-resourcegroepen, gaat u naar het artikel over resourcegroepen.

    4. Voor deze oefening selecteert u Windows als het gekozen besturingssysteem.

    5. Selecteer Verbruiksabonnement voor hostingabonnement.

    6. Bepaal de locatie voor uw resourcegroep (als u een nieuwe resourcegroep maakt). De locatie bevindt zich idealiter in de regio waar de toepassing wordt uitgevoerd. Sommige Azure-assets zijn alleen beschikbaar in bepaalde regio's. Selecteer voor optimale prestaties dezelfde regio als het opslagaccount.

    7. Selecteer voor Opslagde optie Bestaande gebruiken en zoek vervolgens in de vervolgkeuzelijst de eerder gemaakte opslag.

    8. Laat Application Insights uitgeschakeld voor deze oefening.

      details van functie-app invoeren

  4. Klik op de knop Maken.

  5. Nadat u op Maken hebt geklikt, moet u wachten tot de service is gemaakt. Dit kan een minuut duren.

  6. Er wordt een melding weergegeven in de portal zodra het service-exemplaar is gemaakt.

    melding voor nieuwe Azure-portal

  7. Klik op de meldingen om uw nieuwe service-exemplaar te verkennen.

    ga naar de resourcefunctie-app

  8. Klik op de knop Ga naar resource in de melding om uw nieuwe service-exemplaar te verkennen. U wordt naar uw nieuwe exemplaar van de Functie-app-service gebracht.

  9. Beweeg op het dashboard functie-app de muisaanwijzer over Functies, die u in het deelvenster aan de linkerkant vindt, en klik vervolgens op het plusteken (+ ).

    nieuwe functie maken

  10. Controleer op de volgende pagina of Webhook + API is geselecteerd en selecteer voor Kies een taal de optie CSharp, omdat dit de taal is die voor deze zelfstudie wordt gebruikt. Klik ten slotte op de knop Deze functie maken .

    webhook csharp selecteren

  11. U wordt naar de codepagina (run.csx) geleid. Als dat niet het geval is, klikt u op de zojuist gemaakte functie in de lijst Functies in het deelvenster aan de linkerkant.

    nieuwe functie openen

  12. Kopieer de volgende code naar uw functie. Deze functie retourneert eenvoudig een willekeurig geheel getal tussen 0 en 2 wanneer deze wordt aangeroepen. Maak u geen zorgen over de bestaande code, plak deze gerust over de bovenkant ervan.

        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. Selecteer Opslaan.

  14. Het resultaat moet eruitzien zoals in de onderstaande afbeelding.

  15. Klik op Functie-URL ophalen en noteer het weergegeven eindpunt . U moet deze invoegen in de klasse AzureServices die u later in deze cursus gaat maken.

    Functie-eindpunt ophalen

    Functie-eindpunt invoegen

Hoofdstuk 3 - Het Unity-project instellen

Het volgende is een typische set-up voor het ontwikkelen met Mixed Reality en is daarom een goede sjabloon voor andere projecten.

Stel uw mixed reality immersive headset in en test deze.

Notitie

Voor deze cursus hebt u geen bewegingscontrollers nodig. Als u ondersteuning nodig hebt bij het instellen van de immersive headset, gaat u naar het artikel over het instellen van mixed reality.

  1. Open Unity en klik op Nieuw.

    Nieuw Unity-project maken

  2. U moet nu een unity-projectnaam opgeven. Voeg MR_Azure_Functions in. Zorg ervoor dat het projecttype is ingesteld op 3D. Stel de locatie in op een locatie die geschikt is voor u (houd er rekening mee dat dichter bij hoofdmappen beter is). Klik vervolgens op Project maken.

    Geef nieuw unity-project een naam

  3. Als Unity is geopend, is het de moeite waard om te controleren of de standaardscripteditor is ingesteld op Visual Studio. Ga naar Voorkeuren bewerken> en navigeer vervolgens vanuit het nieuwe venster naar Externe hulpprogramma's. Wijzig De externe scripteditor in Visual Studio 2017. Sluit het venster Voorkeuren .

    Visual Studio instellen als scripteditor

  4. Ga vervolgens naar Instellingen voor bestandsbuild> en schakel het platform over naar Universeel Windows-platform door op de knop Platform wisselen te klikken.

    platform overschakelen naar uwp

  5. Ga naarInstellingen voor het bouwen> van bestanden en controleer of:

    1. Doelapparaat is ingesteld op Elk apparaat.

      Voor Microsoft HoloLens stelt u Doelapparaat in op HoloLens.

    2. Buildtype is ingesteld op D3D

    3. SDK is ingesteld op Laatst geïnstalleerd

    4. Visual Studio-versie is ingesteld op Laatst geïnstalleerd

    5. Bouwen en uitvoeren is ingesteld op Lokale computer

    6. Sla de scène op en voeg deze toe aan de build.

      1. U doet dit door Open scènes toevoegen te selecteren. Er wordt een venster voor opslaan weergegeven.

        geopende scènes toevoegen

      2. Maak hiervoor een nieuwe map en een toekomstige scène en selecteer vervolgens de knop Nieuwe map om een nieuwe map te maken, geef deze de naam Scènes.

        map scènes maken

      3. Open de zojuist gemaakte map Scènes en typ in het tekstveld Bestandsnaam:FunctionsScene en druk op Opslaan.

        Scène functies opslaan

  6. De overige instellingen in Build-instellingen moeten voorlopig als standaard worden ingesteld.

    Standaard build-instellingen laten staan

  7. Klik in het venster Build-instellingen op de knop Spelerinstellingen . Hiermee opent u het gerelateerde deelvenster in de ruimte waar de Inspector zich bevindt.

    spelerinstellingen in inspector

  8. In dit deelvenster moeten enkele instellingen worden geverifieerd:

    1. Op het tabblad Overige instellingen :

      1. De runtimeversie van script moet experimenteel zijn (equivalent van.NET 4.6), waardoor de editor opnieuw moet worden gestart.
      2. De back-end van scripts moet .NET zijn
      3. API-compatibiliteitsniveau moet .NET 4.6 zijn
    2. Schakel op het tabblad Publicatie-instellingen onder Mogelijkheden het volgende in:

      • InternetClient

        mogelijkheden instellen

    3. Verderop in het deelvenster, in XR-instellingen (onder Publicatie-instellingen), vinkt u Virtual Reality Ondersteund aan en controleert u of de Windows Mixed Reality SDK is toegevoegd.

      XR-instellingen instellen

  9. Terug in build-instellingenwordt Unity C#-projecten niet langer grijs weergegeven; schakel het selectievakje naast dit selectievakje in.

    tick c#-projecten

  10. Sluit het venster Build Settings.

  11. Sla uw scène en project op (SCÈNE OPSLAAN/>PROJECT OPSLAAN> BESTAND).

Hoofdstuk 4 - Hoofdcamera instellen

Belangrijk

Als u de Unity Set up-onderdelen van deze cursus wilt overslaan en direct wilt doorgaan met code, kunt u dit .unitypackage downloaden en in uw project importeren als een aangepast pakket. Dit bevat ook de DLL's uit het volgende hoofdstuk. Ga na het importeren verder vanaf Hoofdstuk 7.

  1. In het deelvenster Hiërarchie vindt u een object met de naam Hoofdcamera. Dit object vertegenwoordigt uw 'hoofd'-standpunt zodra u zich in uw toepassing bevindt.

  2. Met het Unity-dashboard voor u, selecteert u het GameObject van de hoofdcamera. U zult merken dat in het deelvenster Inspector (meestal aan de rechterkant, in het dashboard) de verschillende onderdelen van dat GameObject worden weergegeven, met Transformeren bovenaan, gevolgd door Camera en enkele andere onderdelen. U moet de transformatie van de hoofdcamera opnieuw instellen, zodat deze correct wordt geplaatst.

  3. Hiervoor selecteert u het tandwielpictogram naast het onderdeel Transformeren van de camera en selecteert u Opnieuw instellen.

    transformatie opnieuw instellen

  4. Werk vervolgens het onderdeel Transformeren bij zodat deze er als volgt uitziet:

Transformeren - positie

X Y Z
0 1 0

Transformeren - Draaien

X Y Z
0 0 0

Transformeren - Schalen

X Y Z
1 1 1

cameratransformatie instellen

Hoofdstuk 5 - De Unity-scène instellen

  1. Klik met de rechtermuisknop in een leeg gebied van het deelvenster Hiërarchie en voeg onder 3D-object een vlak toe.

    nieuw vlak maken

  2. Terwijl het object Plane is geselecteerd, wijzigt u de volgende parameters in het deelvenster Inspector:

Transformeren - positie

X Y Z
0 0 4

Transformeren - Schalen

X Y Z
10 1 10

positie en schaal van het vlak instellen

scèneweergave van vliegtuig

  1. Klik met de rechtermuisknop in een leeg gebied van het deelvenster Hiërarchie en voeg onder 3D-object een kubus toe.

    1. Wijzig de naam van de kubus in GazeButton (druk op F2 als de kubus is geselecteerd).

    2. Wijzig de volgende parameters voor Positie transformeren in het deelvenster Inspector:

      X Y Z
      0 3 5

      transformatie van blikknop instellen

      scèneweergave van de knop staren

    3. Klik op de vervolgkeuzelijst Tag en klik op Tag toevoegen om het deelvenster Tags & Lagen te openen.

      nieuwe tag toevoegen

      plus selecteren

    4. Selecteer de knop + (plus), voer in het veld Nieuwe tagnaamGazeButton in en druk op Opslaan.

      nieuwe tag benoemen

    5. Klik op het object GazeButton in het deelvenster Hierarchy en wijs in het deelvenster Inspector de zojuist gemaakte tag GazeButton toe.

      de knop Staren toewijzen de nieuwe tag

  2. Klik met de rechtermuisknop op het object GazeButton in het deelvenster Hierarchy en voeg een Leeg GameObject toe (dat wordt toegevoegd als een onderliggend object).

  3. Selecteer het nieuwe object en wijzig de naam shapeSpawnPoint.

    1. Wijzig de volgende parameters voor Positie transformeren in het deelvenster Inspector:

      X Y Z
      0 -1 0

      transformatie van spawnpunt van shape bijwerken

      scèneweergave van shape spawnpunt

  4. Vervolgens maakt u een 3D Text-object om feedback te geven over de status van de Azure-service.

    Klik opnieuw met de rechtermuisknop op de Knop Gaze in het deelvenster Hiërarchie en voeg een 3D-object>3D-tekst toe als een onderliggend object.

    nieuw 3D-tekstobject maken

  5. Wijzig de naam van het 3D Text-object in AzureStatusText.

  6. Wijzig de transformatiepositie van het AzureStatusText-object als volgt:

    X Y Z
    0 0 -0,6
  7. Wijzig de transformatieschaal van het AzureStatusText-object als volgt: | X | Y | Z | | :---: | :---: | :---: | | 0,1 | 0,1 | 0,1 |

    Notitie

    Maakt u zich geen zorgen als deze buiten het midden lijkt te staan, want dit wordt opgelost wanneer het onderstaande Text Mesh-onderdeel wordt bijgewerkt.

  8. Wijzig het onderdeel Text Mesh zodat deze overeenkomt met de onderstaande:

    Text Mesh-onderdeel instellen

    Tip

    De geselecteerde kleur hier is Hex color: 000000FF, hoewel u vrij bent om uw eigen kleur te kiezen, zorg er gewoon voor dat het leesbaar is.

  9. De structuur van het deelvenster Hiërarchie moet er nu als volgt uitzien:

    Tekstgaas in hiërarchie

  10. Uw scène ziet er nu als volgt uit:

    Tekstgaas in de scèneweergave

Hoofdstuk 6: Azure Storage voor Unity importeren

U gebruikt Azure Storage voor Unity (die zelf gebruikmaakt van de .Net SDK voor Azure). Meer informatie hierover vindt u in het artikel Azure Storage voor Unity.

Er is momenteel een bekend probleem in Unity waardoor invoegtoepassingen na het importeren opnieuw moeten worden geconfigureerd. Deze stappen (4 - 7 in deze sectie) zijn niet meer vereist nadat de fout is opgelost.

Als u de SDK in uw eigen project wilt importeren, moet u ervoor zorgen dat u de meest recente '.unitypackage' hebt gedownload van GitHub. Ga als volgt verder:

  1. Voeg het bestand .unitypackage toe aan Unity met behulp van de menuoptieAangepast pakket voor hetimporteren> van assets>.

  2. In het venster Unity Package importeren kunt u alles selecteren onderInvoegtoepassingsopslag>. Schakel al het andere uit, omdat dit niet nodig is voor deze cursus.

    importeren naar pakket

  3. Klik op de knop Importeren om de items toe te voegen aan uw project.

  4. Ga in de weergave Project naar de map Opslag onder Invoegtoepassingen en selecteer alleen de volgende invoegtoepassingen:

    • Microsoft.Data.Edm

    • Microsoft.Data.OData

    • Microsoft.WindowsAzure.Storage

    • Newtonsoft.Json

    • System.Spatial

      schakel elk platform uit

  5. Als deze specifieke invoegtoepassingen zijn geselecteerd, schakelt uAny Platform uit en schakelt uWSAPlayer uit en klikt u vervolgens op Toepassen.

    platform-DLL's toepassen

    Notitie

    We markeren deze specifieke invoegtoepassingen om alleen te worden gebruikt in de Unity-editor. Dit komt doordat er verschillende versies van dezelfde invoegtoepassingen in de WSA-map zijn die worden gebruikt nadat het project is geëxporteerd uit Unity.

  6. Selecteer in de map Storage-invoegtoepassing alleen het volgende:

    • Microsoft.Data.Services.Client

      set niet verwerken voor DLL's

  7. Schakel het selectievakje Niet verwerken onder Platforminstellingen in en klik op Toepassen.

    geen verwerking toepassen

    Notitie

    We markeren deze invoegtoepassing niet verwerken omdat de Patcher voor unity-assembly's problemen heeft met het verwerken van deze invoegtoepassing. De invoegtoepassing werkt nog steeds, ook al wordt deze niet verwerkt.

Hoofdstuk 7: De klasse AzureServices maken

De eerste klasse die u gaat maken, is de klasse AzureServices .

De klasse AzureServices is verantwoordelijk voor:

  • Azure-accountreferenties opslaan.

  • Uw Azure-app-functie aanroepen.

  • Het uploaden en downloaden van het gegevensbestand in uw Azure Cloud Storage.

Deze klasse maken:

  1. Klik met de rechtermuisknop in de map Asset in het deelvenster Project, Map maken>. Noem de map Scripts.

    nieuwe map maken

    aanroepmap - scripts

  2. Dubbelklik op de map die u zojuist hebt gemaakt om deze te openen.

  3. Klik met de rechtermuisknop in de mapC#-script maken. > Roep het script AzureServices aan.

  4. Dubbelklik op de nieuwe AzureServices-klasse om deze te openen met Visual Studio.

  5. Voeg de volgende naamruimten toe aan het begin van de 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. Voeg de volgende inspectorvelden toe binnen de klasse 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. Voeg vervolgens de volgende lidvariabelen toe binnen de klasse 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;
    

    Belangrijk

    Zorg ervoor dat u het eindpunt en de verbindingsreeks waarden vervangt door de waarden uit uw Azure-opslag, te vinden in de Azure-portal

  8. Code voor de methoden Awake() en Start() moet nu worden toegevoegd. Deze methoden worden aangeroepen wanneer de klasse wordt geïnitialiseerd:

        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()
        {
    
        }
    

    Belangrijk

    De code voor CallAzureFunctionForNextShape() wordt in een toekomstig hoofdstuk ingevuld.

  9. Verwijder de methode Update(), omdat deze niet door deze klasse wordt gebruikt.

  10. Sla uw wijzigingen op in Visual Studio en ga vervolgens terug naar Unity.

  11. Klik en sleep de klasse AzureServices van de map Scripts naar het object Hoofdcamera in het deelvenster Hiërarchie.

  12. Selecteer de Hoofdcamera, pak vervolgens het onderliggende object AzureStatusText van onder het object GazeButton en plaats het in het referentiedoelveld AzureStatusText in de Inspector om de verwijzing naar het AzureServices-script op te geven.

    tekstreferentiedoel voor azure-status toewijzen

Hoofdstuk 8- De shapeFactory-klasse maken

Het volgende script dat moet worden gemaakt, is de klasse ShapeFactory . De rol van deze klasse is het maken van een nieuwe shape, wanneer dit wordt aangevraagd, en het bijhouden van een geschiedenis van de shapes die zijn gemaakt in een lijst met shapegeschiedenis. Telkens wanneer een shape wordt gemaakt, wordt de lijst Shapegeschiedenis bijgewerkt in de klasse AzureService en vervolgens opgeslagen in uw Azure Storage. Wanneer de toepassing wordt gestart en er een opgeslagen bestand wordt gevonden in uw Azure Storage, wordt de lijst Shapegeschiedenis opgehaald en opnieuw afgespeeld, waarbij het 3D-tekstobject aangeeft of de gegenereerde shape afkomstig is uit opslag of nieuw is.

Ga als volgt te werk om deze klasse te maken:

  1. Ga naar de map Scripts die u eerder hebt gemaakt.

  2. Klik met de rechtermuisknop in de mapC#-script maken. > Roep het script ShapeFactory aan.

  3. Dubbelklik op het nieuwe ShapeFactory-script om het te openen met Visual Studio.

  4. Zorg ervoor dat de klasse ShapeFactory de volgende naamruimten bevat:

        using System.Collections.Generic;
        using UnityEngine;
    
  5. Voeg de onderstaande variabelen toe aan de klasse ShapeFactory en vervang de functies Start() en Awake() door de onderstaande functies:

        /// <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. De methode CreateShape() genereert de primitieve shapes op basis van de opgegeven parameter integer . De Booleaanse parameter wordt gebruikt om op te geven of de momenteel gemaakte shape afkomstig is van opslag of nieuwe. Plaats de volgende code in uw ShapeFactory-klasse , onder de vorige methoden:

        /// <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. Zorg ervoor dat u uw wijzigingen opslaat in Visual Studio voordat u terugkeert naar Unity.

  8. Ga terug naar de Unity Editor en sleep de klasse ShapeFactory van de map Scripts naar het object Hoofdcamera in het deelvenster Hiërarchie.

  9. Als de hoofdcamera is geselecteerd, ziet u dat de verwijzing Spawn Point ontbreekt in het shapeFactory-scriptonderdeel. U kunt dit probleem oplossen door het ShapeSpawnPoint-object van het deelvenster Hiërarchie naar het referentiedoel Spawn-punt te slepen.

    referentiedoel voor shape factory instellen

Hoofdstuk 9- De Gaze-klasse maken

Het laatste script dat u moet maken, is de klasse Gaze .

Deze klasse is verantwoordelijk voor het maken van een Raycast die naar voren wordt geprojecteerd vanaf de hoofdcamera, om te detecteren naar welk object de gebruiker kijkt. In dit geval moet de Raycast bepalen of de gebruiker het object GazeButton in de scène bekijkt en een gedrag activeren.

Deze klasse maken:

  1. Ga naar de map Scripts die u eerder hebt gemaakt.

  2. Klik met de rechtermuisknop in het deelvenster Project opC#-script maken>. Roep het script Gaze aan.

  3. Dubbelklik op het nieuwe Gaze-script om het te openen met Visual Studio.

  4. Zorg ervoor dat de volgende naamruimte boven aan het script is opgenomen:

        using UnityEngine;
    
  5. Voeg vervolgens de volgende variabelen toe in de klasse 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;
    

Belangrijk

Sommige van deze variabelen kunnen worden bewerkt in de editor.

  1. Code voor de methoden Awake() en Start() moet nu worden toegevoegd.

        /// <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. Voeg de volgende code toe, waarmee bij het begin een cursorobject wordt gemaakt, samen met de methode Update(), waarmee de Raycast-methode wordt uitgevoerd, samen met de plaats waar de Booleaanse waarde GazeEnabled is ingeschakeld:

        /// <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. Voeg vervolgens de methode UpdateRaycast() toe, die een Raycast projecteert en het trefferdoel detecteert.

        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. Voeg ten slotte de methode ResetFocusedObject() toe. Hiermee schakelt u de huidige kleur van de Objecten GazeButton in, waarmee wordt aangegeven of er een nieuwe vorm wordt gemaakt of niet.

        /// <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. Sla uw wijzigingen op in Visual Studio voordat u terugkeert naar Unity.

  6. Klik en sleep de klasse Gaze van de map Scripts naar het object Hoofdcamera in het deelvenster Hiërarchie.

Hoofdstuk 10: De klasse AzureServices voltooien

Nu de andere scripts zijn geïmplementeerd, is het nu mogelijk om de klasse AzureServices te voltooien. Dit wordt bereikt door:

  1. Een nieuwe methode toevoegen met de naam CreateCloudIdentityAsync(), om de verificatievariabelen in te stellen die nodig zijn voor de communicatie met Azure.

    Met deze methode wordt ook gecontroleerd op het bestaan van een eerder opgeslagen bestand met de shapelijst.

    Als het bestand wordt gevonden, wordt de gebruiker Gaze uitgeschakeld en wordt het maken van shapes geactiveerd, volgens het patroon van shapes, zoals opgeslagen in het Azure Storage-bestand. De gebruiker kan dit zien, omdat het text mesh de weergave 'Opslag' of 'Nieuw' biedt, afhankelijk van de oorsprong van de shapes.

    Als er geen bestand wordt gevonden, wordt de Gaze ingeschakeld, zodat de gebruiker shapes kan maken wanneer het object GazeButton in de scène wordt bekeken.

        /// <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. Het volgende codefragment is afkomstig van de methode Start(); waarbij een aanroep wordt uitgevoerd naar de methode CreateCloudIdentityAsync(). U kunt de huidige methode Start() gerust kopiëren met de onderstaande stappen:

        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. Vul de code in voor de methode CallAzureFunctionForNextShape(). U gebruikt de eerder gemaakte Azure Function-app om een shape-index aan te vragen. Zodra de nieuwe shape is ontvangen, verzendt deze methode de shape naar de klasse ShapeFactory om de nieuwe shape in de scène te maken. Gebruik de onderstaande code om de hoofdtekst van CallAzureFunctionForNextShape() te voltooien.

        /// <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. Voeg een methode toe om een tekenreeks te maken door de gehele getallen die zijn opgeslagen in de lijst met shapegeschiedenis samen te voegen en op te slaan in uw Azure Storage-bestand.

        /// <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. Voeg een methode toe om de tekst op te halen die is opgeslagen in het bestand in uw Azure Storage-bestand en deze te deserialiseren in een lijst.

  6. Zodra dit proces is voltooid, schakelt de methode de blik opnieuw in, zodat de gebruiker meer shapes aan de scène kan toevoegen.

        ///<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. Sla uw wijzigingen op in Visual Studio voordat u terugkeert naar Unity.

Hoofdstuk 11- De UWP-oplossing bouwen

Ga als volgt te werk om het buildproces te starten:

  1. Ga naar Instellingen voor het>maken van bestanden.

    de app bouwen

  2. Klik op Build. Unity start een Bestandenverkenner-venster, waarin u een map moet maken en selecteren om de app in te bouwen. Maak die map nu en geef deze de naam App. Druk vervolgens op Map selecteren terwijl de map App is geselecteerd.

  3. Unity begint met het bouwen van uw project in de map App .

  4. Zodra Unity klaar is met het bouwen (dit kan enige tijd duren), wordt er een Bestandenverkenner venster geopend op de locatie van uw build (controleer de taakbalk, omdat deze mogelijk niet altijd boven uw vensters wordt weergegeven, maar u wordt op de hoogte gesteld van de toevoeging van een nieuw venster).

Hoofdstuk 12- Uw toepassing implementeren

Uw toepassing implementeren:

  1. Navigeer naar de map App die in het laatste hoofdstuk is gemaakt. U ziet een bestand met de naam van uw apps, met de extensie '.sln', waarop u moet dubbelklikken om het te openen in Visual Studio.

  2. Selecteer in solution platformx86, Lokale computer.

  3. Selecteer foutopsporing in de oplossingsconfiguratie.

    Voor de Microsoft HoloLens vindt u het mogelijk gemakkelijker om dit in te stellen op Externe computer, zodat u niet bent vastgebonden aan uw computer. U moet echter ook het volgende doen:

    • Ken het IP-adres van uw HoloLens, dat u kunt vinden in Instellingen>Netwerk &Geavanceerde opties voor Internet >Wi-Fi>. De IPv4 is het adres dat u moet gebruiken.
    • Zorg ervoor dat de ontwikkelaarsmodus is ingeschakeld; gevonden in Instellingen>Update & Beveiliging>voor ontwikkelaars.

    oplossing implementeren

  4. Ga naar het menu Bouwen en klik op Oplossing implementeren om de toepassing naar uw computer te sideloaden.

  5. Uw app wordt nu weergegeven in de lijst met geïnstalleerde apps, klaar om te worden gestart en getest.

Uw voltooide Azure Functions- en opslagtoepassing

Gefeliciteerd, u hebt een mixed reality-app gemaakt die gebruikmaakt van de Azure Functions- en Azure Storage-services. Uw app kan gebruikmaken van opgeslagen gegevens en een actie bieden op basis van die gegevens.

eindproduct -end

Bonusoefeningen

Oefening 1

Maak een tweede spawnpunt en record van waaruit een object is gemaakt. Wanneer u het gegevensbestand laadt, worden de shapes die worden gegenereerd opnieuw afgespeeld vanaf de locatie waar ze oorspronkelijk zijn gemaakt.

Oefening 2

Maak een manier om de app opnieuw te starten, in plaats van deze telkens opnieuw te moeten openen. Het laden van scènes is een goede plek om te beginnen. Nadat u dit hebt gedaan, maakt u een manier om de opgeslagen lijst in Azure Storage te wissen, zodat deze eenvoudig opnieuw kan worden ingesteld vanuit uw app.