Delen via


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 behouden voor ontwikkelaars die nog steeds op zoek zijn naar richtlijnen bij het ontwikkelen voor die apparaten. Deze zelfstudies worden niet bijgewerkt met de nieuwste toolsets of interacties die worden gebruikt voor HoloLens 2. Ze blijven behouden om door te gaan met het werken op de ondersteunde apparaten. Er is een nieuwe reeks zelfstudies die in de toekomst zullen worden gepost en die laten zien hoe u zich ontwikkelt 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', kunnen uitvoeren in Azure. Dit biedt een manier om werk naar de cloud te delegeren in plaats van uw lokale toepassing, wat veel voordelen kan hebben. Azure Functions ondersteunt verschillende ontwikkeltalen, waaronder C#, F#, Node.js, Java en PHP. Ga naar het Artikel over 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 is. Dit betekent dat Microsoft alle onderhoud en kritieke problemen voor u afhandelt. Ga naar het Artikel over 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. Hiermee staat u de gebruiker toe om rond een scène te staren.
  2. Activeer het spawnen van objecten wanneer de gebruiker naar een 3D-knop kijkt.
  3. De spawned-objecten worden gekozen door een Azure-functie.
  4. Wanneer elk object wordt geactiveerd, slaat de toepassing het objecttype op in een Azure-bestand, dat zich in Azure Storage bevindt.
  5. Bij het laden van een tweede keer worden de Azure File-gegevens opgehaald en gebruikt om de spawningacties van 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. Deze cursus is ontworpen om u te leren hoe u een Azure-service integreert met uw Unity-project. Het is uw taak om de kennis die u uit deze cursus krijgt te gebruiken om uw mixed reality-toepassing te verbeteren.

Ondersteuning voor apparaten

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

Notitie

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

Vereisten

Notitie

Deze zelfstudie is ontworpen voor ontwikkelaars die basiservaring hebben met Unity en C#. Houd er ook rekening mee dat de vereisten en schriftelijke instructies in dit document staan voor wat is getest en geverifieerd op het moment van schrijven (mei 2018). U kunt de nieuwste software gebruiken, zoals vermeld in het artikel over de installatie van de hulpprogramma's , hoewel er niet van wordt uitgegaan dat de informatie in deze cursus perfect overeenkomt met wat u vindt in nieuwere software dan 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 te maken dat in deze zelfstudie wordt genoemd in een hoofdmap of in een near-rootmap (lange mappaden kunnen problemen veroorzaken tijdens de build).

Hoofdstuk 1: Azure Portal

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

  1. Meld u aan bij de 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 voor hulp bij het instellen van uw nieuwe account.

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

    azure Storage Search

    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. Zodra u op Maken hebt geklikt:

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

    2. Selecteer Resource Manager voor het implementatiemodel.

    3. Selecteer Opslag (algemeen gebruik v1) als soort account.

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

    5. Voor replicatie selecteert u geografisch redundante opslag met leestoegang (RA-GRS).

    6. Selecteer bij Prestaties de optie Standaard.

    7. Laat Beveiligde overdracht vereist als Uitgeschakeld.

    8. Selecteer een abonnement.

    9. Kies een resourcegroep of maak een nieuwe. Een resourcegroep biedt een manier om de toegang te bewaken, te beheren, facturering in te richten en te beheren voor een verzameling Azure-assets. 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 weten over Azure-resourcegroepen, gaat u naar het artikel over de resourcegroep.

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

    11. Selecteer Maken.

      invoerservicegegevens

  5. Nadat u op Maken hebt geklikt, moet u wachten totdat 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.

    naar de resource gaan

  8. Klik op de knop Ga naar de 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 vergelijkbaar 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 AzureServices-klasse , die u later gaat maken.

    verbindingsreeks kopiëren

Hoofdstuk 2: Een Azure-functie instellen

U schrijft nu een Azure-functie 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 de Azure-portal op Nieuw in de linkerbovenhoek en 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.

    informatie over functie-app

  3. Zodra u op Maken hebt geklikt:

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

    2. Selecteer uw voorkeursabonnement.

    3. Kies een resourcegroep of maak een nieuwe. Een resourcegroep biedt een manier om de toegang te bewaken, te beheren, facturering in te richten en te beheren voor een verzameling Azure-assets. 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 weten over Azure-resourcegroepen, gaat u naar het artikel over de resourcegroep.

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

    5. Selecteer Verbruiksabonnement voor het hostingabonnement.

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

    7. Voor Opslag selecteert u Bestaande gebruiken en zoekt u vervolgens de eerder gemaakte opslag met behulp van het vervolgkeuzemenu.

    8. Laat Application Insights uitgeschakeld voor deze oefening.

      details van invoerfunctie-app

  4. Klik op de knop Maken.

  5. Nadat u op Maken hebt geklikt, moet u wachten totdat 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 azure-portalmelding

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

    naar de resourcefunctie-app gaan

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

  9. Beweeg op het dashboard van de functie-app de muisaanwijzer over Functies, in het deelvenster aan de linkerkant 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 CSharp, omdat dit de taal is die wordt gebruikt voor deze zelfstudie. Klik ten slotte op de knop Deze functie maken.

    webhook csharp selecteren

  11. U moet naar de codepagina (run.csx) gaan, 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. Met deze functie wordt eenvoudig een willekeurig geheel getal tussen 0 en 2 geretourneerd wanneer deze wordt aangeroepen. U hoeft zich geen zorgen te maken over de bestaande code, u kunt deze over de bovenkant plakken.

        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 eindpunt dat wordt weergegeven. U moet deze invoegen in de AzureServices-klasse die u later in deze cursus gaat maken.

    Functie-eindpunt ophalen

    Functie-eindpunt invoegen

Hoofdstuk 3- Het Unity-project instellen

Hieronder ziet u een typische configuratie voor het ontwikkelen met Mixed Reality en is als zodanig een goede sjabloon voor andere projecten.

Stel uw mixed reality immersive headset in en test deze.

Notitie

U hebt geen Motion Controllers nodig voor deze cursus. Als u ondersteuning nodig hebt bij het instellen van de insluitende 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 (vergeet niet, dichter bij hoofdmappen is beter). Klik vervolgens op Project maken.

    Geef een 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 naar Instellingen voor bestandsbuild>en zorg ervoor dat:

    1. Het 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 Meest recent 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. Doe dit door Open Scènes toevoegen te selecteren. Er wordt een venster voor opslaan weergegeven.

        open scènes toevoegen

      2. Maak hiervoor een nieuwe map, en voor elke toekomst scène, 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 vervolgens in het tekstvak Bestandsnaam FunctionsScene en druk op Opslaan.

        Scène functies opslaan

  6. De overige instellingen, in Build-instellingen, moeten voorlopig standaard blijven staan.

    Laat de standaard build-instellingen 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. Scripting Runtime-versie moet experimenteel (.NET 4.6 Equivalent) zijn, waardoor de editor opnieuw moet worden opgestart.
      2. Back-end voor 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), tikt u op Virtual Reality Ondersteund, controleert u of de Windows Mixed Reality SDK is toegevoegd.

      XR-instellingen instellen

  9. Terug in Build Settings Unity C# Projects wordt niet meer 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 (FILE>SAVE SCENE/ FILE>SAVE PROJECT).

Hoofdstuk 4 - Hoofdcamera instellen

Belangrijk

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

  1. In het deelvenster Hiërarchie vindt u een object met de naam Hoofdcamera, dit object vertegenwoordigt uw 'hoofd'-weergavepunt zodra u zich 'binnen' uw toepassing bevindt.

  2. Selecteer het Main Camera GameObject met het Unity-dashboard voor u. U ziet dat in het Inspector Panel (meestal aan de rechterkant, in het dashboard) de verschillende onderdelen van dat GameObject worden weergegeven, met Transform bovenaan, gevolgd door Camera en enkele andere onderdelen. U moet de transformatie van de hoofdcamera opnieuw instellen, zodat deze correct is ingesteld.

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

    transformatie opnieuw instellen

  4. Werk vervolgens het transformatieonderdeel bij zodat het er als volgt uitziet:

Transformeren - positie

X Y Z
0 1 0

Transformatie - Rotatie

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, onder 3D-object, en voeg een vlak toe.

    nieuw vlak maken

  2. Terwijl het object Vlak 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 vlak instellen

scèneweergave van vliegtuig

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

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

    2. Wijzig de volgende parameters voor Transform Position in het Inspector Panel:

      X Y Z
      0 3 5

      knoptransformatie instellen

      scèneweergave van de knop

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

      nieuwe tag toevoegen

      plus selecteren

    4. Selecteer de knop + (plus) en typ GazeButton in het veld Nieuwe tagnaam en druk op Opslaan.

      naam nieuwe tag

    5. Klik op het Object GazeButton in het deelvenster Hiërarchie en wijs in het Inspector-deelvenster de zojuist gemaakte GazeButton-tag toe.

      knop Voor het toewijzen van de nieuwe tag

  2. Klik met de rechtermuisknop op het Object GazeButton in het hiërarchievenster en voeg een leeg GameObject toe (dat wordt toegevoegd als een onderliggend object).

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

    1. Wijzig de volgende parameters voor Transform Position in het Inspector Panel:

      X Y Z
      0 -1 0

      Transformatie van shape spawnpunt bijwerken

      scèneweergave shape spawn

  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 GazeButton in het deelvenster Hiërarchie en voeg als onderliggend object een 3D-object>3D-tekst toe.

    nieuw 3D-tekstobject maken

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

  6. Wijzig de AzureStatusText-object Transform Position 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 | 0.1 |

    Notitie

    Maak u geen zorgen als het buiten het midden lijkt te zijn, omdat dit wordt opgelost wanneer het onderstaande Text Mesh-onderdeel wordt bijgewerkt.

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

    Text Mesh-onderdeel instellen

    Tip

    De geselecteerde kleur hier is Hex-kleur: 000000FF, hoewel u gerust uw eigen kleur kunt kiezen, zorg er dan voor dat deze leesbaar is.

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

    Tekstmaas in hiërarchie

  10. Uw scène moet er nu als volgt uitzien:

    Tekstmaas in scèneweergave

Hoofdstuk 6: Azure Storage importeren voor Unity

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

Er is momenteel een bekend probleem in Unity waarvoor 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 wilt importeren in uw eigen project, moet u ervoor zorgen dat u de nieuwste '.unitypackage' hebt gedownload vanuit GitHub. Ga als volgt verder:

  1. Voeg het .unitypackage-bestand toe aan Unity met behulp van de menuoptie Aangepast pakket voor assets>importeren.>

  2. In het vak Import Unity Package dat verschijnt, kunt u alles selecteren onder Plugin>Storage. Schakel alles uit, omdat dit niet nodig is voor deze cursus.

    importeren in pakket

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

  4. Ga in de projectweergave 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

      Alle platformen uitschakelen

  5. Als deze specifieke invoegtoepassingen zijn geselecteerd, schakelt u Any Platform uit en schakelt u WSAPlayer uit en klikt u 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 uit Unity is geëxporteerd.

  6. Selecteer alleen in de map storage-invoegtoepassing :

    • Microsoft.Data.Services.Client

      instellen niet verwerken voor dll's

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

    geen verwerking toepassen

    Notitie

    We markeren deze invoegtoepassing 'Niet verwerken' omdat de Unity-assemblypatcher problemen heeft met het verwerken van deze invoegtoepassing. De invoegtoepassing werkt nog steeds, ook al wordt deze niet verwerkt.

Hoofdstuk 7: de AzureServices-klasse maken

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

De AzureServices-klasse is verantwoordelijk voor:

  • Het opslaan van azure-accountreferenties.

  • Uw Azure-app-functie aanroepen.

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

Ga als volgt te werk om deze klasse te maken:

  1. Klik met de rechtermuisknop in de assetmap, in het deelvenster Project, Map maken>. Geef de mapscripts een naam.

    nieuwe map maken

    oproepmap - scripts

  2. Dubbelklik op de zojuist gemaakte map om deze te openen.

  3. Klik met de rechtermuisknop in de map, C#-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 Inspector Fields toe binnen de AzureServices-klasse :

        /// <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 in de AzureServices-klasse :

        /// <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 verbindingsreeks waarden vervangt door de waarden uit uw Azure-opslag, die u in Azure Portal vindt

  8. De methoden Code for Awake() en Start() moeten 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

    In een toekomstig hoofdstuk vullen we de code voor CallAzureFunctionForNextShape() in.

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

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

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

  12. Selecteer de hoofdcamera en pak vervolgens het onderliggende object AzureStatusText onder het GazeButton-object en plaats het in het doelveld van de AzureStatusText-referentie, in inspector, om de verwijzing naar het AzureServices-script op te geven.

    referentiedoel voor azure-statustekst toewijzen

Hoofdstuk 8: de klasse ShapeFactory maken

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

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 map, C#-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 variabelen:

        /// <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. Met de methode CreateShape() worden de primitieve shapes gegenereerd op basis van de opgegeven integerparameter . De Booleaanse parameter wordt gebruikt om op te geven of de momenteel gemaakte shape afkomstig is van opslag of nieuw. 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. Sla uw wijzigingen op in Visual Studio voordat u terugkeert naar Unity.

  8. Klik in de Unity Editor en sleep de ShapeFactory-klasse van de map Scripts naar het object Main Camera in het deelvenster Hierarchy.

  9. Als de hoofdcamera is geselecteerd, ziet u dat het scriptonderdeel ShapeFactory ontbreekt in de spawnpuntverwijzing . Als u dit wilt herstellen, sleept u het Object ShapeSpawnPoint van het deelvenster Hiërarchie naar het doel van het spawnpunt .

    Referentiedoel voor shape factory instellen

Hoofdstuk 9 - De klasse Gaze maken

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

Deze klasse is verantwoordelijk voor het maken van een Raycast die 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 GazeButton-object in de scène bekijkt en een gedrag activeert.

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 het deelvenster Project, C#-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 een cursorobject aan het begin wordt gemaakt, samen met de methode Update(), waarmee de Raycast-methode wordt uitgevoerd, samen met de plaats waar de Booleaanse waarde GazeEnabled is in- of uitgezet:

        /// <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, waarmee de huidige kleur van de GazeButton-objecten wordt in-/uitschakelen, waarmee wordt aangegeven of er een nieuwe shape 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 vanuit de map Scripts naar het object Hoofdcamera in het deelvenster Hiërarchie.

Hoofdstuk 10: de AzureServices-klasse voltooien

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

  1. Voeg een nieuwe methode toe 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 het maken van shape's door de gebruiker uitgeschakeld en wordt het maken van shapes geactiveerd, zoals is opgeslagen in het Azure Storage-bestand. De gebruiker kan dit zien, omdat de 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 bij het bekijken van het GazeButton-object in de scène.

        /// <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 uit de methode Start(). Hierbij wordt een aanroep uitgevoerd naar de methode CreateCloudIdentityAsync(). U kunt gerust kopiëren via uw huidige Start() -methode, 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 samen te voegen die zijn opgeslagen in de lijst met shapegeschiedenissen en deze 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 Opbouwen. Unity start een Bestandenverkenner-venster waarin u een map moet maken en vervolgens een map selecteert waarin u de app wilt inbouwen. Maak die map nu en noem deze app. Druk vervolgens op Map selecteren terwijl de app-map is geselecteerd.

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

  4. Zodra Unity klaar is met bouwen (het 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 ontvangt een melding over 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, dus om het te openen in Visual Studio.

  2. Selecteer x86 in het Solution Platform, Local Machine.

  3. Selecteer foutopsporing in de oplossingsconfiguratie.

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

    • Ken het IP-adres van uw HoloLens, die u kunt vinden in de geavanceerde opties voor het instellingennetwerk>en internet-Wi-Fi>>. De IPv4 is het adres dat u moet gebruiken.
    • Zorg ervoor dat de ontwikkelaarsmodus is ingeschakeld. Deze vindt u in Instellingen>bijwerken en beveiliging>voor ontwikkelaars.

    oplossing implementeren

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

  5. Uw app moet nu worden 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 gebouwd die gebruikmaakt van zowel de Azure Functions- als Azure Storage-services. Uw app kan tekenen op opgeslagen gegevens en een actie leveren op basis van die gegevens.

eindproduct -end

Bonusoefeningen

Oefening 1

Maak een tweede spawnpunt en record op basis waarvan een object is gemaakt. Wanneer u het gegevensbestand laadt, kunt u de shapes die worden gegenereerd opnieuw afspelen 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 openen. Scènes laden is een goede plek om te beginnen. Maak daarna een manier om de opgeslagen lijst in Azure Storage te wissen, zodat deze eenvoudig opnieuw kan worden ingesteld vanuit uw app.