HoloLens (1. Generation) und Azure 305: Funktionen und Speicher


Hinweis

Die Tutorials der Mixed Reality Academy wurden im Hinblick auf HoloLens (1. Gen.) und immersive Mixed Reality-Headsets entworfen. Daher halten wir es für wichtig, diese Tutorials für Entwickler verfügbar zu halten, die noch nach Anleitung beim Entwickeln für diese Geräte suchen. Diese Tutorials werden nicht mit den neuesten Toolsets oder Interaktionen aktualisiert, die für HoloLens 2 verwendet werden. Sie werden gewartet, um weiterhin auf den unterstützten Geräten zu funktionieren. Es wird eine neue Reihe von Tutorials geben, die in Zukunft veröffentlicht werden, die zeigen, wie für HoloLens 2 entwickelt werden kann. Dieser Hinweis wird mit einem Link zu diesen Tutorials aktualisiert, wenn sie veröffentlicht werden.


Endprodukt -start

In diesem Kurs erfahren Sie, wie Sie Azure Functions und Daten mit einer Azure Storage-Ressource in einer Mixed Reality-Anwendung erstellen und verwenden.

Azure Functions ist ein Microsoft-Dienst, mit dem Entwickler kleine Codeteile, "Funktionen", in Azure ausführen können. Dies bietet eine Möglichkeit, Arbeit an die Cloud zu delegieren, anstatt an Ihre lokale Anwendung, was viele Vorteile haben kann. Azure Functions unterstützt mehrere Entwicklungssprachen, darunter C#, F#, Node.js, Java und PHP. Weitere Informationen finden Sie im artikel Azure Functions.

Azure Storage ist ein Microsoft-Clouddienst, mit dem Entwickler Daten speichern können, mit der Versicherung, dass sie hochverfügbar, sicher, dauerhaft, skalierbar und redundant sind. Dies bedeutet, dass Microsoft alle Wartungs- und kritischen Probleme für Sie übernimmt. Weitere Informationen finden Sie im Artikel Azure Storage.

Nach Abschluss dieses Kurses verfügen Sie über eine immersive Mixed Reality-Headset-Anwendung, die folgendes ausführen kann:

  1. Erlauben Sie dem Benutzer, eine Szene zu betrachten.
  2. Lösen Sie das Spawning von Objekten aus, wenn der Benutzer eine 3D-Schaltfläche anschaut.
  3. Die gespawnten Objekte werden von einer Azure-Funktion ausgewählt.
  4. Während jedes Objekt erstellt wird, speichert die Anwendung den Objekttyp in einer Azure-Datei in Azure Storage.
  5. Beim zweiten Laden werden die Azure-Dateidaten abgerufen und zum Wiedergeben der Spawningaktionen aus dem vorherigen instance der Anwendung verwendet.

In Ihrer Anwendung liegt es bei Ihnen, wie Sie die Ergebnisse in Ihr Design integrieren. In diesem Kurs erfahren Sie, wie Sie einen Azure-Dienst in Ihr Unity-Projekt integrieren. Es ist Ihre Aufgabe, das Wissen, das Sie aus diesem Kurs gewinnen, zu nutzen, um Ihre Mixed Reality-Anwendung zu verbessern.

Geräteunterstützung

Kurs HoloLens Immersive Headsets
MR und Azure 305: Funktionen und Speicher ✔️ ✔️

Hinweis

Während sich dieser Kurs hauptsächlich auf Windows Mixed Reality immersiven Headsets (VR) konzentriert, können Sie das, was Sie in diesem Kurs lernen, auch auf Microsoft HoloLens anwenden. Während Sie den Kurs befolgen, werden Ihnen Notizen zu allen Änderungen angezeigt, die Sie möglicherweise zur Unterstützung von HoloLens anwenden müssen.

Voraussetzungen

Hinweis

Dieses Tutorial richtet sich an Entwickler, die über grundlegende Erfahrungen mit Unity und C# verfügen. Bitte beachten Sie auch, dass die Voraussetzungen und schriftlichen Anweisungen in diesem Dokument das darstellen, was zum Zeitpunkt des Schreibens (Mai 2018) getestet und überprüft wurde. Sie können die neueste Software verwenden, wie im Artikel Installieren der Tools aufgeführt, aber es sollte nicht davon ausgegangen werden, dass die Informationen in diesem Kurs perfekt dem entsprechen, was Sie in neuerer Software finden, als die unten aufgeführten.

Wir empfehlen die folgende Hard- und Software für diesen Kurs:

Vorbereitung

Um Probleme beim Erstellen dieses Projekts zu vermeiden, wird dringend empfohlen, das in diesem Tutorial erwähnte Projekt in einem Stamm- oder Fast-Root-Ordner zu erstellen (lange Ordnerpfade können zur Buildzeit Zu Problemen führen).

Kapitel 1: Azure-Portal

Um den Azure Storage-Dienst verwenden zu können, müssen Sie ein Speicherkonto im Azure-Portal erstellen und konfigurieren.

  1. Melden Sie sich beim Azure-Portal an.

    Hinweis

    Wenn Sie noch nicht über ein Azure-Konto verfügen, müssen Sie ein Azure-Konto erstellen. Wenn Sie dieses Tutorial in einer Unterrichts- oder Labsituation befolgen, bitten Sie Ihren Kursleiter oder einen der Verantwortlichen um Hilfe beim Einrichten Ihres neuen Kontos.

  2. Nachdem Sie angemeldet sind, klicken Sie in der oberen linken Ecke auf Neu , suchen Sie nach Speicherkonto, und klicken Sie auf DIE EINGABETASTE.

    Azure Storage Search

    Hinweis

    Das Wort Neu wurde in neueren Portalen möglicherweise durch Ressource erstellen ersetzt.

  3. Die neue Seite enthält eine Beschreibung des Azure Storage-Kontodiensts . Wählen Sie unten links in dieser Eingabeaufforderung die Schaltfläche Erstellen aus, um eine Zuordnung zu diesem Dienst zu erstellen.

    Dienst erstellen

  4. Nachdem Sie auf Erstellen geklickt haben:

    1. Fügen Sie einen Namen für Ihr Konto ein, und beachten Sie, dass dieses Feld nur Zahlen und Kleinbuchstaben akzeptiert.

    2. Wählen Sie unter Bereitstellungsmodelldie Option Ressourcen-Manager aus.

    3. Wählen Sie unter Kontoartdie Option Speicher (universell v1) aus.

    4. Bestimmen Sie den Speicherort für Ihre Ressourcengruppe (wenn Sie eine neue Ressourcengruppe erstellen). Der Speicherort befindet sich idealerweise in der Region, in der die Anwendung ausgeführt wird. Einige Azure-Ressourcen sind nur in bestimmten Regionen verfügbar.

    5. Wählen Sie unter Replikationdie Option Read-Access-Geo-Redundant Storage (RA-GRS) aus.

    6. Wählen Sie für Leistung die Option Standard aus.

    7. Lassen Sie sichere Übertragung erforderlich als Deaktiviert.

    8. Wählen Sie ein Abonnementaus.

    9. Wählen Sie eine Ressourcengruppe aus, oder erstellen Sie eine neue. Eine Ressourcengruppe bietet eine Möglichkeit zum Überwachen, Steuern des Zugriffs, Bereitstellen und Verwalten der Abrechnung für eine Sammlung von Azure-Ressourcen. Es wird empfohlen, alle Azure-Dienste, die einem einzelnen Projekt (z. B. diesen Labs) zugeordnet sind, unter einer gemeinsamen Ressourcengruppe zu halten.

      Wenn Sie mehr über Azure-Ressourcengruppen erfahren möchten, lesen Sie den Artikel Ressourcengruppe.

    10. Sie müssen auch bestätigen, dass Sie die für diesen Dienst geltenden Geschäftsbedingungen verstanden haben.

    11. Klicken Sie auf Erstellen.

      Eingabedienstinformationen

  5. Nachdem Sie auf Erstellen geklickt haben, müssen Sie warten, bis der Dienst erstellt wird. Dies kann eine Minute dauern.

  6. Eine Benachrichtigung wird im Portal angezeigt, sobald der Dienst instance erstellt wurde.

    Neue Benachrichtigung im Azure-Portal

  7. Klicken Sie auf die Benachrichtigungen, um Ihre neue Dienst-instance zu erkunden.

    Zur Ressource wechseln

  8. Klicken Sie in der Benachrichtigung auf die Schaltfläche Zu Ressource wechseln, um Ihren neuen Dienst instance zu erkunden. Sie werden zu Ihrem neuen Speicherkontodienst instance weitergeleitet.

    Zugriffsschlüssel

  9. Klicken Sie auf Zugriffsschlüssel, um die Endpunkte für diesen Clouddienst anzuzeigen. Verwenden Sie Editor oder ähnliches, um einen Ihrer Schlüssel zur späteren Verwendung zu kopieren. Beachten Sie auch den Wert der Verbindungszeichenfolge , da er in der AzureServices-Klasse verwendet wird, die Sie später erstellen werden.

    Verbindungszeichenfolge kopieren

Kapitel 2: Einrichten einer Azure-Funktion

Sie schreiben jetzt eine Azure-Funktion in den Azure-Dienst.

Sie können eine Azure-Funktion verwenden, um fast alles zu tun, was Sie mit einer klassischen Funktion in Ihrem Code tun würden. Der Unterschied ist, dass jede Anwendung auf diese Funktion zugreifen kann, die über Anmeldeinformationen für den Zugriff auf Ihr Azure-Konto verfügt.

So erstellen Sie eine Azure-Funktion:

  1. Klicken Sie in Ihrem Azure-Portal oben links auf Neu , suchen Sie nach Funktions-App, und klicken Sie auf DIE EINGABETASTE.

    Erstellen einer Funktions-App

    Hinweis

    Das Wort Neu wurde in neueren Portalen möglicherweise durch Ressource erstellen ersetzt.

  2. Die neue Seite enthält eine Beschreibung des Azure Function App Service. Wählen Sie unten links in dieser Eingabeaufforderung die Schaltfläche Erstellen aus, um eine Zuordnung zu diesem Dienst zu erstellen.

    Funktions-App-Informationen

  3. Nachdem Sie auf Erstellen geklickt haben:

    1. Geben Sie einen App-Namen an. Hier können nur Buchstaben und Zahlen verwendet werden (Groß- oder Kleinbuchstaben sind zulässig).

    2. Wählen Sie Ihr bevorzugtes Abonnement aus.

    3. Wählen Sie eine Ressourcengruppe aus, oder erstellen Sie eine neue. Eine Ressourcengruppe bietet eine Möglichkeit zum Überwachen, Steuern des Zugriffs, Bereitstellen und Verwalten der Abrechnung für eine Sammlung von Azure-Ressourcen. Es wird empfohlen, alle Azure-Dienste, die einem einzelnen Projekt (z. B. diesen Labs) zugeordnet sind, unter einer gemeinsamen Ressourcengruppe zu halten.

      Wenn Sie mehr über Azure-Ressourcengruppen erfahren möchten, lesen Sie den Artikel Ressourcengruppe.

    4. Wählen Sie für diese Übung Windows als ausgewähltes Betriebssystem aus.

    5. Wählen Sie Verbrauchsplan für den Hostingplan aus.

    6. Bestimmen Sie den Speicherort für Ihre Ressourcengruppe (wenn Sie eine neue Ressourcengruppe erstellen). Der Speicherort befindet sich idealerweise in der Region, in der die Anwendung ausgeführt wird. Einige Azure-Ressourcen sind nur in bestimmten Regionen verfügbar. Um eine optimale Leistung zu erzielen, wählen Sie dieselbe Region wie das Speicherkonto aus.

    7. Wählen Sie unter Speicher die Option Vorhandenes verwenden aus, und suchen Sie dann über das Dropdownmenü nach Ihrem zuvor erstellten Speicher.

    8. Lassen Sie Application Insights für diese Übung deaktiviert.

      Details der Eingabefunktions-App

  4. Klicken Sie auf die Schaltfläche Erstellen .

  5. Nachdem Sie auf Erstellen geklickt haben, müssen Sie warten, bis der Dienst erstellt wird. Dies kann eine Minute dauern.

  6. Eine Benachrichtigung wird im Portal angezeigt, sobald der Dienst instance erstellt wurde.

    Neue Azure-Portalbenachrichtigung

  7. Klicken Sie auf die Benachrichtigungen, um Ihre neue Dienst-instance zu erkunden.

    Zur Ressourcenfunktions-App wechseln

  8. Klicken Sie in der Benachrichtigung auf die Schaltfläche Zu Ressource wechseln, um Ihren neuen Dienst instance zu erkunden. Sie werden zu Ihrem neuen Funktions-App-Dienst instance weitergeleitet.

  9. Zeigen Sie auf der Dashboard Funktions-App mit dem Mauszeiger auf Funktionen, die sich im bereich auf der linken Seite befindet, und klicken Sie dann auf das Symbol + (plus).

    Neue Funktion erstellen

  10. Stellen Sie auf der nächsten Seite sicher, dass Webhook + API ausgewählt ist, und wählen Sie unter Sprache auswählendie Option CSharp aus, da dies die sprache ist, die für dieses Tutorial verwendet wird. Klicken Sie abschließend auf die Schaltfläche Diese Funktion erstellen .

    web hook csharp auswählen

  11. Sie sollten zur Codepage (run.csx) weitergeleitet werden, wenn nicht, klicken Sie auf die neu erstellte Funktion in der Liste Funktionen im Bereich auf der linken Seite.

    Neue Funktion öffnen

  12. Kopieren Sie den folgenden Code in Ihre Funktion. Diese Funktion gibt einfach eine zufällige ganze Zahl zwischen 0 und 2 zurück, wenn sie aufgerufen wird. Machen Sie sich keine Sorgen um den vorhandenen Code, fügen Sie ihn oben ein.

        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. Wählen Sie Speichern aus.

  14. Das Ergebnis sollte wie in der folgenden Abbildung aussehen.

  15. Klicken Sie auf Funktions-URL abrufen, und notieren Sie sich den angezeigten Endpunkt . Sie müssen es in die AzureServices-Klasse einfügen, die Sie später in diesem Kurs erstellen werden.

    Funktionsendpunkt abrufen

    Funktionsendpunkt einfügen

Kapitel 3: Einrichten des Unity-Projekts

Das Folgende ist eine typische Einrichtung für die Entwicklung mit Mixed Reality und ist daher eine gute Vorlage für andere Projekte.

Richten Sie Ihr immersives Mixed Reality-Headset ein und testen Sie es.

Hinweis

Für diesen Kurs benötigen Sie keine Bewegungscontroller. Wenn Sie Unterstützung beim Einrichten des immersiven Headsets benötigen, lesen Sie den Artikel Mixed Reality-Einrichtung.

  1. Öffnen Sie Unity, und klicken Sie auf Neu.

    Erstellen eines neuen Unity-Projekts

  2. Sie müssen nun einen Unity-Projektnamen angeben. Fügen Sie MR_Azure_Functions ein. Stellen Sie sicher, dass der Projekttyp auf 3D festgelegt ist. Legen Sie den Speicherort auf einen für Sie geeigneten Ort fest (denken Sie daran, dass näher an Stammverzeichnissen besser ist). Klicken Sie dann auf Projekt erstellen.

    Geben Sie dem neuen Unity-Projekt einen Namen

  3. Wenn Unity geöffnet ist, lohnt es sich, zu überprüfen, ob der Standardskript-Editor auf Visual Studio festgelegt ist. Navigieren Sie zu Einstellungen bearbeiten>, und navigieren Sie dann im neuen Fenster zu Externe Tools. Ändern Sie den externen Skript-Editor in Visual Studio 2017. Schließen Sie das Fenster Einstellungen.

    Festlegen von Visual Studio als Skript-Editor

  4. Wechseln Sie als Nächstes zuDateierstellungseinstellungen>, und wechseln Sie die Plattform auf Universelle Windows-Plattform, indem Sie auf die Schaltfläche Plattform wechseln klicken.

    Plattform wechseln zu uwp

  5. Wechseln Sie zuDateibuildeinstellungen>, und stellen Sie sicher, dass:

    1. Zielgerät ist auf Beliebiges Gerät festgelegt.

      Legen Sie für Microsoft HoloLens Zielgerät auf HoloLens fest.

    2. Buildtyp ist auf D3D festgelegt

    3. SDK ist auf Zuletzt installiert festgelegt.

    4. Visual Studio-Version ist auf Zuletzt installiert festgelegt.

    5. Build and Run ist auf Lokaler Computer festgelegt.

    6. Speichern Sie die Szene, und fügen Sie sie dem Build hinzu.

      1. Wählen Sie dazu Offene Szenen hinzufügen aus. Es wird ein Fenster zum Speichern angezeigt.

        Hinzufügen von offenen Szenen

      2. Erstellen Sie einen neuen Ordner für diese und jede zukünftige Szene, und wählen Sie dann die Schaltfläche Neuer Ordner aus, um einen neuen Ordner zu erstellen, und nennen Sie ihn Szenen.

        Ordner

      3. Öffnen Sie Den neu erstellten Ordner Scenes , und geben Sie im Textfeld Dateiname:den Namen FunctionsScene ein, und drücken Sie dann Speichern.

        Szenen zum Speichern von Funktionen

  6. Die restlichen Einstellungen in Buildeinstellungen sollten vorerst als Standard beibehalten werden.

    Behalten Sie die Standardbuildeinstellungen bei.

  7. Klicken Sie im Fenster Buildeinstellungen auf die Schaltfläche Playereinstellungen . Dadurch wird der zugehörige Bereich in dem Bereich geöffnet, in dem sich der Inspektor befindet.

    Playereinstellungen im Inspektor

  8. In diesem Bereich müssen einige Einstellungen überprüft werden:

    1. Auf der Registerkarte Andere Einstellungen :

      1. Die Skriptlaufzeitversion sollte experimentell (.NET 4.6 Equivalent) sein, was einen Neustart des Editors auslöst.
      2. Skript-Back-End sollte .NET sein
      3. API-Kompatibilitätsgrad sollte .NET 4.6 sein
    2. Überprüfen Sie auf der Registerkarte Veröffentlichungseinstellungen unter Funktionen Folgendes:

      • InternetClient

        Funktionen festlegen

    3. Aktivieren Sie weiter unten im Bereich unter XR-Einstellungen (unter Veröffentlichungseinstellungen) Das Kontrollkästchen Virtual Reality Wird unterstützt, stellen Sie sicher, dass das Windows Mixed Reality SDK hinzugefügt wurde.

      Festlegen von XR-Einstellungen

  9. Zurück in den Buildeinstellungenunity C#-Projekte ist nicht mehr ausgegraut. aktivieren Sie das Kontrollkästchen neben diesem.

    tick c#-Projekte

  10. Schließen Sie das Fenster „Build Settings“ (Buildeinstellungen).

  11. Speichern Sie Ihre Szene und Ihr Projekt (FILE>SAVE SCENE /FILE>SAVE PROJECT).

Kapitel 4: Einrichten der Hauptkamera

Wichtig

Wenn Sie die Unity Setup-Komponenten dieses Kurses überspringen und direkt mit dem Code fortfahren möchten, können Sie dieses UNITY-Paket herunterladen und als benutzerdefiniertes Paket in Ihr Projekt importieren. Dies enthält auch die DLLs aus dem nächsten Kapitel. Fahren Sie nach dem Import aus Kapitel 7 fort.

  1. Im Hierarchiebereich finden Sie ein Objekt namens Hauptkamera. Dieses Objekt stellt Ihren "Kopf"-Standpunkt dar, sobald Sie sich "in" Ihrer Anwendung befinden.

  2. Wählen Sie mit dem Unity-Dashboard vor Ihnen das Hauptkamera-GameObject aus. Sie werden feststellen, dass im Inspektorbereich (in der Regel rechts im Dashboard) die verschiedenen Komponenten dieses GameObject angezeigt werden, wobei die Transformation oben, gefolgt von der Kamera und einigen anderen Komponenten, angezeigt wird. Sie müssen die Transformation der Hauptkamera zurücksetzen, damit sie richtig positioniert ist.

  3. Wählen Sie hierzu das Zahnradsymbol neben der Transformationskomponente der Kamera und dann Zurücksetzen aus.

    Zurücksetzen der Transformation

  4. Aktualisieren Sie dann die Transformationskomponente so, dass sie wie folgt aussieht:

Transformieren – Position

X J Z
0 1 0

Transformieren – Drehung

X J Z
0 0 0

Transformieren – Skalieren

X J Z
1 1 1

Kameratransformation festlegen

Kapitel 5: Einrichten der Unity-Szene

  1. Klicken Sie mit der rechten Maustaste in einen leeren Bereich des Hierarchiebereichs, und fügen Sie unter 3D-Objekt eine Ebene hinzu.

    Erstellen einer neuen Ebene

  2. Wenn das Plane-Objekt ausgewählt ist, ändern Sie die folgenden Parameter im Inspektorbereich:

Transformieren – Position

X J Z
0 0 4

Transformieren – Skalieren

X J Z
10 1 10

Festlegen der Ebenenposition und Skalierung

Szenenansicht der Ebene

  1. Klicken Sie mit der rechten Maustaste in einen leeren Bereich des Hierarchiebereichs, und fügen Sie unter 3D-Objekt einen Cube hinzu.

    1. Benennen Sie den Cube in GazeButton um (wenn der Cube ausgewählt ist, drücken Sie "F2").

    2. Ändern Sie die folgenden Parameter für Transformationsposition im Inspektorbereich:

      X J Z
      0 3 5

      Transformation der Schaltfläche

      Szenenansicht der Schaltfläche

    3. Klicken Sie auf die Dropdownschaltfläche Tag und dann auf Tag hinzufügen , um den Bereich Tags & Ebenen zu öffnen.

      Neues Tag hinzufügen

      Wählen Sie plus aus

    4. Wählen Sie die Schaltfläche + (Plus) aus, geben Sie im Feld Neuer TagnamegazeButton ein, und drücken Sie Speichern.

      name new tag

    5. Klicken Sie im Hierarchiebereich auf das GazeButton-Objekt, und weisen Sie im Inspektorbereich das neu erstellte GazeButton-Tag zu.

      Dem neuen Tag die Schaltfläche

  2. Klicken Sie im Hierarchiebereich mit der rechten Maustaste auf das GazeButton-Objekt, und fügen Sie ein leeres GameObject hinzu (das als untergeordnetes Objekt hinzugefügt wird).

  3. Wählen Sie das neue Objekt aus, und benennen Sie es in ShapeSpawnPoint um.

    1. Ändern Sie die folgenden Parameter für Transformationsposition im Inspektorbereich:

      X J Z
      0 -1 0

      Transformation des Shape-Spawnpunkts aktualisieren

      Szenenansicht des Shape-Spawnpunkts

  4. Als Nächstes erstellen Sie ein 3D-Text-Objekt, um Feedback zur status des Azure-Diensts zu geben.

    Klicken Sie im Hierarchiebereich erneut mit der rechten Maustaste auf gazeButton , und fügen Sie ein 3D-Objekt>3D Text-Objekt als untergeordnetes Objekt hinzu.

    Erstellen eines neuen 3D-Textobjekts

  5. Benennen Sie das 3D Text-Objekt in AzureStatusText um.

  6. Ändern Sie das Transformationsposition des AzureStatusText-Objekts wie folgt:

    X J Z
    0 0 -0,6
  7. Ändern Sie das AzureStatusText-ObjektTransform Scale wie folgt: | X | Y | Z | | :---: | :---: | :---: | | 0.1 | 0.1 | 0.1 |

    Hinweis

    Machen Sie sich keine Sorgen, wenn es nicht zentral zu sein scheint, da dies behoben wird, wenn die folgende Text mesh-Komponente aktualisiert wird.

  8. Ändern Sie die Text mesh-Komponente so, dass sie mit dem folgenden übereinstimmt:

    Textgitterkomponente festlegen

    Tipp

    Die hier ausgewählte Farbe ist Hexadezimalfarbe: 000000FF, obwohl Sie sich frei entscheiden können, stellen Sie sicher, dass sie lesbar ist.

  9. Die Struktur des Hierarchiebereichs sollte nun wie folgt aussehen:

    Textgitter in der Hierarchie

  10. Ihre Szene sollte jetzt wie folgt aussehen:

    Textgitter in der Szenenansicht

Kapitel 6: Importieren von Azure Storage für Unity

Sie verwenden Azure Storage für Unity (das selbst das .NET SDK für Azure nutzt). Weitere Informationen hierzu finden Sie im Artikel Azure Storage für Unity.

Es gibt derzeit ein bekanntes Problem in Unity, das erfordert, dass Plug-Ins nach dem Import neu konfiguriert werden müssen. Diese Schritte (4 bis 7 in diesem Abschnitt) sind nicht mehr erforderlich, nachdem der Fehler behoben wurde.

Um das SDK in Ihr eigenes Projekt zu importieren, stellen Sie sicher, dass Sie das neueste ".unitypackage" von GitHub heruntergeladen haben. Gehen Sie nun wie folgt vor:

  1. Fügen Sie unitypackage-Datei zu Unity hinzu, indem Sie die Menüoption Assets>Import Package>Custom Package (Benutzerdefiniertes Paket importieren) verwenden.

  2. Im eingeblendeten Feld Unity-Paket importieren können Sie unter Plug-In-Speicher> alles auswählen. Deaktivieren Sie alles andere, da es für diesen Kurs nicht benötigt wird.

    Importieren in Paket

  3. Klicken Sie auf die Schaltfläche Importieren , um die Elemente zu Ihrem Projekt hinzuzufügen.

  4. Wechseln Sie in der Projektansicht unter Plugins zum Ordner Storage, und wählen Sie nur die folgenden Plug-Ins aus:

    • Microsoft.Data.Edm

    • Microsoft.Data.OData

    • Microsoft.WindowsAzure.Storage

    • Newtonsoft.Json

    • System.Spatial

      Deaktivieren Sie Beliebige Plattform.

  5. Wenn Diese spezifischen Plug-Ins ausgewählt sind, deaktivieren SieBeliebige Plattform , und deaktivieren SieWSAPlayer , und klicken Sie dann auf Übernehmen.

    Anwenden von Plattform-DLLs

    Hinweis

    Wir markieren diese speziellen Plug-Ins, die nur im Unity-Editor verwendet werden sollen. Dies liegt daran, dass es verschiedene Versionen der gleichen Plug-Ins im WSA-Ordner gibt, die verwendet werden, nachdem das Projekt aus Unity exportiert wurde.

  6. Wählen Sie im Ordner Storage-Plug-In nur Folgendes aus:

    • Microsoft.Data.Services.Client

      set don't process for DLLs (set don't process for DLLs)

  7. Aktivieren Sie das Kontrollkästchen Nicht verarbeiten unter Plattformeinstellungen , und klicken Sie auf Übernehmen.

    keine Verarbeitung anwenden

    Hinweis

    Wir markieren dieses Plug-In mit "Nicht verarbeiten", da der Unity-Assemblypatcher Probleme mit der Verarbeitung dieses Plug-Ins hat. Das Plug-In funktioniert weiterhin, obwohl es nicht verarbeitet wird.

Kapitel 7: Erstellen der AzureServices-Klasse

Die erste Klasse, die Sie erstellen, ist die AzureServices-Klasse .

Die AzureServices-Klasse ist für Folgendes verantwortlich:

  • Speichern von Azure-Kontoanmeldeinformationen.

  • Aufrufen der Azure-App-Funktion.

  • Der Upload und Download der Datendatei in Azure Cloud Storage.

So erstellen Sie diese Klasse:

  1. Klicken Sie mit der rechten Maustaste auf den Ressourcenordner, der sich im Projektbereich ordner erstellen>befindet. Nennen Sie den Ordner Skripts.

    Neuen Ordner erstellen

    Aufrufordner – Skripts

  2. Doppelklicken Sie auf den soeben erstellten Ordner, um ihn zu öffnen.

  3. Klicken Sie mit der rechten Maustaste in den OrdnerC#-Skript erstellen>. Rufen Sie das Skript AzureServices auf.

  4. Doppelklicken Sie auf die neue AzureServices-Klasse , um sie mit Visual Studio zu öffnen.

  5. Fügen Sie die folgenden Namespaces am Anfang der AzureServices hinzu:

        using System;
        using System.Threading.Tasks;
        using UnityEngine;
        using Microsoft.WindowsAzure.Storage;
        using Microsoft.WindowsAzure.Storage.File;
        using System.IO;
        using System.Net;
    
  6. Fügen Sie die folgenden Inspektorfelder in der AzureServices-Klasse hinzu:

        /// <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. Fügen Sie dann die folgenden Membervariablen in der AzureServices-Klasse hinzu:

        /// <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;
    

    Wichtig

    Stellen Sie sicher, dass Sie den Endpunkt und Verbindungszeichenfolge Werte durch die Werte aus Ihrem Azure-Speicher ersetzen, die sie im Azure-Portal finden.

  8. Code für die Methoden Awake() und Start() muss jetzt hinzugefügt werden. Diese Methoden werden aufgerufen, wenn die -Klasse initialisiert wird:

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

    Wichtig

    Wir werden den Code für CallAzureFunctionForNextShape() in einem zukünftigen Kapitel ausfüllen.

  9. Löschen Sie die Update() -Methode, da diese Klasse sie nicht verwendet.

  10. Speichern Sie Ihre Änderungen in Visual Studio, und kehren Sie dann zu Unity zurück.

  11. Klicken Sie auf die AzureServices-Klasse , und ziehen Sie sie aus dem Ordner Skripts in das Objekt Hauptkamera im Hierarchiebereich.

  12. Wählen Sie die Hauptkamera aus, greifen Sie dann unter dem GazeButton-Objekt nach dem untergeordneten AzureStatusText-Objekt, und platzieren Sie es im Verweiszielfeld AzureStatusText im Inspektor, um den Verweis auf das AzureServices-Skript bereitzustellen.

    Zuweisen eines Azure status-Textverweisziels

Kapitel 8: Erstellen der ShapeFactory-Klasse

Das nächste zu erstellende Skript ist die ShapeFactory-Klasse . Die Rolle dieser Klasse besteht darin, bei Bedarf ein neues Shape zu erstellen und einen Verlauf der in einer Shape-Verlaufsliste erstellten Shapes zu speichern. Jedes Mal, wenn ein Shape erstellt wird, wird die Liste Des Shape-Verlaufs in der AzureService-Klasse aktualisiert und dann in Ihrem Azure Storage gespeichert. Wenn die Anwendung gestartet wird und eine gespeicherte Datei in Azure Storage gefunden wird, wird die Liste Des Shape-Verlaufs abgerufen und wiedergegeben, wobei das 3D Text-Objekt angibt, ob die generierte Form aus dem Speicher stammt oder neu.

So erstellen Sie diese Klasse:

  1. Wechseln Sie zum Ordner Skripts, den Sie zuvor erstellt haben.

  2. Klicken Sie mit der rechten Maustaste in den OrdnerC#-Skript erstellen>. Rufen Sie das Skript ShapeFactory auf.

  3. Doppelklicken Sie auf das neue ShapeFactory-Skript , um es mit Visual Studio zu öffnen.

  4. Stellen Sie sicher, dass die ShapeFactory-Klasse die folgenden Namespaces enthält:

        using System.Collections.Generic;
        using UnityEngine;
    
  5. Fügen Sie der ShapeFactory-Klasse die unten gezeigten Variablen hinzu, und ersetzen Sie die Funktionen Start() und Awake() durch die folgenden:

        /// <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. Die CreateShape()- Methode generiert die primitiven Shapes basierend auf dem angegebenen ganzzahligen Parameter. Der boolesche Parameter wird verwendet, um anzugeben, ob die aktuell erstellte Form aus dem Speicher oder neu ist. Platzieren Sie den folgenden Code in Ihrer ShapeFactory-Klasse unter den vorherigen 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. Speichern Sie ihre Änderungen in Visual Studio, bevor Sie zu Unity zurückkehren.

  8. Klicken Sie zurück im Unity-Editor auf die ShapeFactory-Klasse , und ziehen Sie sie aus dem Ordner Skripts in das Hauptkameraobjekt im Hierarchiebereich.

  9. Wenn die Hauptkamera ausgewählt ist, werden Sie feststellen, dass der ShapeFactory-Skriptkomponente der Verweis auf den Spawn-Punkt fehlt. Um dies zu beheben, ziehen Sie das ShapeSpawnPoint-Objekt aus dem Hierarchiebereich auf das Verweisziel Spawn-Punkt .

    Festlegen des Referenzziels für die Shape-Factory

Kapitel 9: Erstellen der Gaze-Klasse

Das letzte Skript, das Sie erstellen müssen, ist die Gaze-Klasse .

Diese Klasse ist dafür verantwortlich, einen Raycast zu erstellen, der von der Hauptkamera nach vorne projiziert wird, um zu erkennen, welches Objekt der Benutzer betrachtet. In diesem Fall muss raycast erkennen, ob der Benutzer das GazeButton-Objekt in der Szene betrachtet, und ein Verhalten auslösen.

So erstellen Sie diese Klasse:

  1. Wechseln Sie zum Ordner Skripts, den Sie zuvor erstellt haben.

  2. Klicken Sie mit der rechten Maustaste im Projektbereich,C#-Skript erstellen>. Rufen Sie das Skript Gaze auf.

  3. Doppelklicken Sie auf das neue Gaze-Skript, um es mit Visual Studio zu öffnen.

  4. Stellen Sie sicher, dass der folgende Namespace oben im Skript enthalten ist:

        using UnityEngine;
    
  5. Fügen Sie dann die folgenden Variablen der Gaze-Klasse hinzu:

        /// <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;
    

Wichtig

Einige dieser Variablen können im Editor bearbeitet werden.

  1. Code für die Methoden Awake() und Start() muss jetzt hinzugefügt werden.

        /// <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. Fügen Sie den folgenden Code hinzu, mit dem beim Start ein Cursorobjekt erstellt wird, zusammen mit der Update() -Methode, die die Raycast-Methode ausführen wird, und dort, wo gazeEnabled boolean umschaltbar ist:

        /// <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. Fügen Sie als Nächstes die UpdateRaycast() -Methode hinzu, die einen Raycast projiziert und das Trefferziel erkennt.

        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. Fügen Sie abschließend die ResetFocusedObject() -Methode hinzu, die die aktuelle Farbe der GazeButton-Objekte umschaltet und angibt, ob eine neue Form erstellt wird oder nicht.

        /// <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. Speichern Sie Ihre Änderungen in Visual Studio, bevor Sie zu Unity zurückkehren.

  6. Klicken Sie auf die Gaze-Klasse , und ziehen Sie sie aus dem Ordner Skripts in das Objekt Hauptkamera im Hierarchiebereich.

Kapitel 10: Abschließen der AzureServices-Klasse

Nachdem die anderen Skripts vorhanden sind, ist es jetzt möglich, die AzureServices-Klasseabzuschließen. Dies wird erreicht durch:

  1. Hinzufügen einer neuen Methode mit dem Namen CreateCloudIdentityAsync() zum Einrichten der Authentifizierungsvariablen, die für die Kommunikation mit Azure erforderlich sind.

    Diese Methode prüft auch, ob eine zuvor gespeicherte Datei vorhanden ist, die die Shape-Liste enthält.

    Wenn die Datei gefunden wird, wird die Benutzeranzeige deaktiviert und die Erstellung von Formen entsprechend dem Muster der Formen ausgelöst, wie sie in der Azure Storage-Datei gespeichert sind. Der Benutzer kann dies sehen, da das Textgitter abhängig vom Ursprung der Formen die Anzeige "Speicher" oder "Neu" bereitstellt.

    Wenn keine Datei gefunden wird, wird das Gaze aktiviert, sodass der Benutzer Formen erstellen kann, wenn er das GazeButton-Objekt in der Szene betrachtet.

        /// <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. Der nächste Codeausschnitt stammt aus der Start() -Methode. wobei ein Aufruf der CreateCloudIdentityAsync() -Methode erfolgt. Kopieren Sie ihre aktuelle Start()- Methode mit folgendem Text:

        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. Geben Sie den Code für die Methode CallAzureFunctionForNextShape() ein. Sie verwenden die zuvor erstellte Azure-Funktions-App , um einen Shape-Index anzufordern. Sobald die neue Form empfangen wurde, sendet diese Methode das Shape an die ShapeFactory-Klasse , um das neue Shape in der Szene zu erstellen. Verwenden Sie den folgenden Code, um den Text von CallAzureFunctionForNextShape() zu vervollständigen.

        /// <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. Fügen Sie eine Methode hinzu, um eine Zeichenfolge zu erstellen, indem Sie die ganzen Zahlen verketten, die in der Shape-Verlaufsliste gespeichert sind, und speichern Sie sie in Ihrer Azure Storage-Datei.

        /// <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. Fügen Sie eine Methode hinzu, um den text abzurufen, der sich in der Datei in Ihrer Azure Storage-Datei befindet, und deserialisieren Sie ihn in einer Liste.

  6. Sobald dieser Prozess abgeschlossen ist, aktiviert die Methode den Blick erneut, sodass der Benutzer der Szene weitere Shapes hinzufügen kann.

        ///<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. Speichern Sie Ihre Änderungen in Visual Studio, bevor Sie zu Unity zurückkehren.

Kapitel 11: Erstellen der UWP-Lösung

So starten Sie den Buildvorgang:

  1. Wechseln Sie zuDateibuildeinstellungen>.

    Erstellen der App

  2. Klicken Sie auf Erstellen. Unity startet ein Explorer Fenster, in dem Sie einen Ordner erstellen und dann auswählen müssen, in dem die App erstellt werden soll. Erstellen Sie diesen Ordner jetzt, und nennen Sie ihn App. Drücken Sie dann, wenn der Ordner App ausgewählt ist, Ordner auswählen.

  3. Unity beginnt mit dem Erstellen Ihres Projekts im Ordner App .

  4. Sobald Unity das Erstellen abgeschlossen hat (es kann einige Zeit dauern), öffnet es ein Explorer Fenster am Speicherort Ihres Builds (überprüfen Sie Ihre Taskleiste, da es möglicherweise nicht immer über Ihren Fenstern angezeigt wird, Sie aber über das Hinzufügen eines neuen Fensters benachrichtigt).

Kapitel 12: Bereitstellen Ihrer Anwendung

So stellen Sie Ihre Anwendung bereit:

  1. Navigieren Sie zum Ordner App , der im letzten Kapitel erstellt wurde. Es wird eine Datei mit dem Namen Ihrer Apps mit der Erweiterung ".sln" angezeigt, auf die Sie doppelklicken sollten, um sie in Visual Studio zu öffnen.

  2. Wählen Sie auf der Lösungsplattformdie Option x86, Lokaler Computer aus.

  3. Wählen Sie in der Projektmappenkonfigurationdebuggen aus.

    Für die Microsoft HoloLens ist es möglicherweise einfacher, dies auf Remotecomputer festzulegen, sodass Sie nicht an Ihren Computer angebunden werden. Sie müssen jedoch auch die folgenden Schritte ausführen:

    • Kennen Sie die IP-Adresse Ihrer HoloLens, die Sie im Einstellungsnetzwerk>& Internet>Wi-Fi>Advanced Options finden können. IPv4 ist die Adresse, die Sie verwenden sollten.
    • Stellen Sie sicher , dass der Entwicklermodusaktiviert ist. finden Sie unter Einstellungen>Update & Sicherheit>für Entwickler.

    Lösung bereitstellen

  4. Wechseln Sie zum Menü Erstellen , und klicken Sie auf Lösung bereitstellen , um die Anwendung auf Ihren Computer querzuladen.

  5. Ihre App sollte jetzt in der Liste der installierten Apps angezeigt werden, die zum Starten und Testen bereit sind!

Ihre fertige Azure Functions- und Speicheranwendung

Herzlichen Glückwunsch! Sie haben eine Mixed Reality-App erstellt, die sowohl die Azure Functions- als auch azure Storage-Dienste nutzt. Ihre App kann auf gespeicherten Daten zeichnen und basierend auf diesen Daten eine Aktion bereitstellen.

Endprodukt

Zusatzübungen

Übung 1

Erstellen Sie einen zweiten Spawnpunkt und einen Datensatz, aus dem ein Spawnpunkt ein Objekt erstellt wurde. Wenn Sie die Datendatei laden, geben Sie die Shapes wieder, die von dem ursprünglich erstellten Speicherort abgerufen werden.

Übung 2

Erstellen Sie eine Möglichkeit, die App neu zu starten, anstatt sie jedes Mal erneut öffnen zu müssen. Das Laden von Szenen ist ein guter Ausgangspunkt. Erstellen Sie anschließend eine Möglichkeit, die gespeicherte Liste in Azure Storage zu löschen, damit sie problemlos von Ihrer App zurückgesetzt werden kann.