Delen via


HoloLens (1e generatie) en Azure 309: Application Insights

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.

Het welkomstscherm van de Mixed Reality Academy-zelfstudie.

In deze cursus leert u hoe u Application Insights-mogelijkheden toevoegt aan een mixed reality-toepassing met behulp van de api Azure-toepassing Insights om analyses te verzamelen met betrekking tot gebruikersgedrag.

Application Insights is een Microsoft-service waarmee ontwikkelaars analyses van hun toepassingen kunnen verzamelen en beheren vanuit een gebruiksvriendelijke portal. De analyse kan van alles zijn, van prestaties tot aangepaste gegevens die u wilt verzamelen. Ga naar de Application Insights-pagina 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 toe dat de gebruiker naar een scène kijkt en navigeert.
  2. Activeer het verzenden van analyses naar de Application Insights-service met behulp van gaze- en nabijheidsobjecten in de scène.
  3. De app roept ook de Service aan, waarbij informatie wordt opgehaald over welk object het meest door de gebruiker is benaderd, binnen de afgelopen 24 uur. Dat object wijzigt de kleur in groen.

In deze cursus leert u hoe u de resultaten van de Application Insights-service kunt ophalen in een voorbeeldtoepassing op basis van Unity. Het is aan u om deze concepten toe te passen op een aangepaste toepassing die u mogelijk bouwt.

Ondersteuning voor apparaten

Cursus HoloLens Insluitende headsets
MR en Azure 309: Application Insights ✔️ ✔️

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. Wanneer u HoloLens gebruikt, ziet u mogelijk echo tijdens spraakopname.

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 er op het moment van schrijven is getest en geverifieerd (juli 2018). U bent vrij om de nieuwste software te gebruiken, zoals vermeld in het artikel over de installatie van de hulpprogramma's , hoewel wordt ervan 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

Als u problemen wilt voorkomen bij het bouwen van dit project, wordt u sterk aangeraden het project in deze zelfstudie te maken in een hoofdmap of een near-rootmap (lange mappaden kunnen problemen veroorzaken tijdens de build).

Waarschuwing

Houd er rekening mee dat gegevens die naar Application Insights gaan tijd in beslag neemt, dus wees geduldig. Als u wilt controleren of de Service uw gegevens heeft ontvangen, bekijkt u hoofdstuk 14, waarmee u kunt zien hoe u door de portal navigeert.

Hoofdstuk 1: Azure Portal

Als u Application Insights wilt gebruiken, moet u een Application Insights-service maken en configureren in Azure Portal.

  1. Meld u aan bij Azure-portal.

    Notitie

    Als u nog geen Azure-account hebt, moet u er een maken. Als u deze zelfstudie volgt in een leslokaal- of labsituatie, vraagt u uw docent of een van de proctors 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 Application Insights en klikt u op Enter.

    Notitie

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

    Schermopname van Azure Portal, Insight is gemarkeerd in het deelvenster Alles.

  3. De nieuwe pagina aan de rechterkant geeft een beschrijving van de Azure-toepassing Insights Service. Selecteer linksonder op deze pagina de knop Maken om een koppeling met deze service te maken.

    Schermopname van het application insights-scherm, Maken is gemarkeerd.

  4. Zodra u op Maken hebt geklikt:

    1. Voeg de gewenste naam in voor dit service-exemplaar.

    2. Als toepassingstype selecteert u Algemeen.

    3. Selecteer een geschikt abonnement.

    4. 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 is raadzaam om alle Azure-services die zijn gekoppeld aan één project (zoals deze cursussen) onder een gemeenschappelijke resourcegroep te houden.

      Als u meer wilt weten over Azure-resourcegroepen, gaat u naar het artikel over de resourcegroep.

    5. Selecteer een Locatie.

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

    7. Selecteer Maken.

      Schermopname van het Application Insights-venster. Naam en toepassingstype zijn gemarkeerd.

  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.

    Schermopname van een gedeelte van het menulint, het meldingspictogram is gemarkeerd.

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

    Schermopname van het dialoogvenster Implementatie is voltooid. Ga naar de resource is gemarkeerd.

  8. Klik op de knop Ga naar de resource in de melding om uw nieuwe service-exemplaar te verkennen. U wordt naar uw nieuwe Application Insights Service-exemplaar gebracht.

    Schermopname van het Application Insights Service-exemplaar waarin de exemplaarnaam MyNewInsight is.

    Notitie

    Houd deze webpagina open en gemakkelijk toegankelijk, u komt hier vaak terug om de verzamelde gegevens te zien.

    Belangrijk

    Als u Application Insights wilt implementeren, moet u drie (3) specifieke waarden gebruiken: Instrumentatiesleutel, toepassings-id en API-sleutel. Hieronder ziet u hoe u deze waarden ophaalt uit uw service. Noteer deze waarden op een lege Kladblok-pagina , omdat u deze binnenkort in uw code zult gebruiken.

  9. Als u de instrumentatiesleutel wilt vinden, moet u omlaag schuiven in de lijst met servicefuncties en Eigenschappen selecteren. Op het weergegeven tabblad wordt de servicesleutel weergegeven.

    Schermopname van servicefuncties, Eigenschappen is gemarkeerd in de sectie Configureren en Instrumentatiesleutel is gemarkeerd in het hoofdvenster.

  10. Een beetje onder Eigenschappen vindt u API Access, waarop u moet klikken. In het deelvenster aan de rechterkant wordt de toepassings-id van uw app opgegeven.

    Schermopname van servicefuncties, A P I Access is gemarkeerd. Een P I-sleutel en toepassings-ID maken zijn gemarkeerd in het hoofdvenster.

  11. Als het deelvenster Toepassings-id nog steeds is geopend, klikt u op API-sleutel maken. Hiermee opent u het deelvenster API-sleutel maken.

    Schermopname van het deelvenster A P I-sleutel maken.

  12. Typ in het nu geopende deelvenster API-sleutel maken een beschrijving en schakel de drie vakken in.

  13. Klik op Sleutel genereren. Uw API-sleutel wordt gemaakt en weergegeven.

    Schermopname van het sleutelvenster A P I maken met de informatie over de nieuwe servicesleutel.

    Waarschuwing

    Dit is de enige keer dat uw servicesleutel wordt weergegeven, dus zorg ervoor dat u er nu een kopie van maakt.

Hoofdstuk 2 - Het Unity-project instellen

Hier volgt een typische installatie voor het ontwikkelen met mixed reality en is daarom een goede sjabloon voor andere projecten.

  1. Open Unity en klik op Nieuw.

    Schermopname van het venster Unity-projecten. Er worden geen projectgegevens weergegeven.

  2. U moet nu een Unity-projectnaam opgeven, MR_Azure_Application_Insights invoegen. Zorg ervoor dat de sjabloon 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.

    Schermopname van het venster Nieuwe Unity-projecten met projectgegevens.

  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 .

    Schermopname van Visual Studio is ingesteld als de externe 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.

    Schermopname van het venster Build Settings, met de selectielijst Platform. Universeel Windows-platform is geselecteerd.

  5. Ga naar Instellingen voor bestandsbuild > en zorg ervoor dat:

    1. Doelapparaat is ingesteld op Elk apparaat

      Voor de Microsoft HoloLens stelt u Doelapparaat in op HoloLens.

    2. Buildtype is ingesteld op D3D

    3. SDK is ingesteld op Laatst geïnstalleerd

    4. Bouwen en uitvoeren is ingesteld op lokale computer

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

        Schermopname van het venster Build Settings, Add Open Scenes is geselecteerd.

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

        Schermopname van het venster Scène opslaan, de map Scènes is geselecteerd.

      3. Open de zojuist gemaakte map Scènes en klik vervolgens in de bestandsnaam: tekstveld, typ ApplicationInsightsScene en klik vervolgens op Opslaan.

        Schermopname van het venster Scène opslaan met de bestandsnaam ingevoerd.

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

  7. Selecteer In het venster Build Settings de optie Player Settings. Hiermee opent u het bijbehorende deelvenster in de ruimte waar de Inspector zich bevindt.

    Schermopname van het tabblad Inspector met Player Settings.

  8. In dit deelvenster moeten enkele instellingen worden geverifieerd:

    1. Op het tabblad Overige instellingen :

      1. De runtimeversie van scripting 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

      Schermopname van het tabblad Inspector met details in de configuratiesectie van Overige instellingen.

    2. Schakel op het tabblad Publicatie-instellingen onder Mogelijkheden het volgende in:

      • InternetClient

        Schermopname van de lijst Capabilities, internetclient is ingeschakeld.

    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.

      Schermopname van de sectie X R Settings, Virtual Reality Supported is ingeschakeld.

  9. In Build Settings wordt Unity C# Projects niet meer grijs weergegeven. Schakel het selectievakje naast dit selectievakje in.

  10. Sluit het venster Build Settings.

  11. Sla uw scène en project op (FILE>SAVE SCENE/ FILE>SAVE PROJECT).

Hoofdstuk 3: Het Unity-pakket importeren

Belangrijk

Als u de Unity Set up-onderdelen van deze cursus wilt overslaan en direct in code wilt doorgaan, kunt u deze Azure-MR-309.unitypackage downloaden, het 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 6.

Belangrijk

Als u Application Insights in Unity wilt gebruiken, moet u het DLL-bestand importeren, samen met de Newtonsoft-DLL. 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 Application Insights in uw eigen project wilt importeren, moet u ervoor zorgen dat u de .unitypackage hebt gedownload met de invoegtoepassingen. Ga als volgt verder:

  1. Voeg the.unitypackage** toe aan Unity met behulp van de menuoptie Aangepast pakket voor > assets > importeren.

  2. Controleer in het vak Import Unity Package dat verschijnt of alles onder (en inclusief) invoegtoepassingen is geselecteerd.

    Schermopname van het dialoogvenster Unity-pakket importeren met alle ingeschakelde items.

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

  4. Ga naar de map Insights onder Invoegtoepassingen in de projectweergave en selecteer alleen de volgende invoegtoepassingen:

    • Microsoft.ApplicationInsights

    Schermopname van het deelvenster Project, de map Insights is geopend.

  5. Als deze invoegtoepassing is geselecteerd, controleert u of Any Platform is uitgeschakeld en controleert u of WSAPlayer ook is uitgeschakeld en klikt u vervolgens op Toepassen. Dit is alleen om te bevestigen dat de bestanden correct zijn geconfigureerd.

    Schermopname van het deelvenster Inspector met Editor en Standalone ingeschakeld.

    Notitie

    Als u de invoegtoepassingen als deze markeert, configureert u deze zodanig dat ze alleen worden gebruikt in de Unity Editor. Er is een andere set DLL's in de WSA-map die wordt gebruikt nadat het project is geëxporteerd uit Unity.

  6. Vervolgens moet u de WSA-map openen in de map Insights . U ziet een kopie van hetzelfde bestand dat u hebt geconfigureerd. Selecteer dit bestand en controleer vervolgens in de inspector of Any Platform is uitgeschakeld en zorg ervoor dat alleen WSAPlayer is ingeschakeld. Klik op Toepassen.

    Schermopname van het deelvenster Inspector met W S A Player ingeschakeld.

  7. U moet nu stap 4-6 volgen, maar in plaats daarvan voor de Newtonsoft-invoegtoepassingen. Zie de onderstaande schermopname voor hoe het resultaat eruit moet zien.

    Schermopname van vier weergaven van de deelvensters Project en Inspector met de resultaten van het instellen van de newtonsoft-map en invoegtoepassingselecties.

Hoofdstuk 4 - De camera- en gebruikersbesturingselementen instellen

In dit hoofdstuk stelt u de camera en de besturingselementen in zodat de gebruiker de scène kan zien en verplaatsen.

  1. Klik met de rechtermuisknop in een leeg gebied in het deelvenster Hiërarchie en klik vervolgens op Leeg maken>.

    Schermopname van het deelvenster Hierarchy, Create Empty is geselecteerd.

  2. Wijzig de naam van het nieuwe lege GameObject in Camera Parent.

    Schermopname van het deelvenster Hierarchy met Camera Parent geselecteerd. Het deelvenster Inspector

  3. Klik met de rechtermuisknop in een leeg gebied in het deelvenster Hiërarchie en vervolgens op 3D-object en vervolgens op Sphere.

  4. Wijzig de naam van de bol in de rechterhand.

  5. De transformatieschaal van de rechterhand instellen op 0.1, 0.1, 0.1

    Schermopname van de deelvensters Hiërarchie en Inspector, de sectie Transformeren in het deelvenster Inspector is gemarkeerd.

  6. Verwijder het Sphere Collider-onderdeel uit de rechterhand door op het tandwiel in het Sphere Collider-onderdeel te klikken en vervolgens component verwijderen.

    Schermopname van het deelvenster Inspector, het tandwielpictogram en het onderdeel Verwijderen zijn gemarkeerd in de sectie Sphere Collider.

  7. Sleep in het deelvenster Hiërarchie de hoofdcamera en de rechterobjecten naar het bovenliggende object Camera.

    Schermopname van het deelvenster Hierarchy met Main Camera geselecteerd, het deelvenster Inspector toont Main Camera ingeschakeld.

  8. Stel de transformatiepositie van zowel de hoofdcamera als het object rechts in op 0, 0, 0.

    Schermopname van het deelvenster Hierarchy met Main Camera geselecteerd, Transform-instellingen zijn gemarkeerd in het deelvenster Inspector.

    Schermopname van het deelvenster Hiërarchie met Rechterhand geselecteerd. Transformatie-instellingen zijn gemarkeerd in het deelvenster Inspector.

Hoofdstuk 5: de objecten instellen in de Unity-scène

U gaat nu enkele basisshapes maken voor uw scène, waarmee de gebruiker kan communiceren.

  1. Klik met de rechtermuisknop in een leeg gebied in het deelvenster Hiërarchie en selecteer vervolgens Op 3D-object de optie Vlak.

  2. Stel de positie van de vlaktransformatie in op 0, -1, 0.

  3. Stel de schaal van de vlaktransformatie in op 5, 1, 5.

    Schermopname van de deelvensters Scène, Hiërarchie en Inspector. De sectie Transformeren in het deelvenster Inspector is gemarkeerd.

  4. Maak een basismateriaal voor gebruik met uw Plane-object , zodat de andere shapes gemakkelijker te zien zijn. Navigeer naar het deelvenster Project, klik met de rechtermuisknop en klik vervolgens op Maken, gevolgd door Map, om een nieuwe map te maken. Noem het materiaal.

    Schermopname van het deelvenster Project met Maken en Map gemarkeerd. Schermopname van het deelvenster Project. Materialen zijn gemarkeerd in het deelvenster Assets.

  5. Open de map Materialen en klik met de rechtermuisknop op Maken en vervolgens Op Materiaal om een nieuw materiaal te maken. Noem het blauw.

    Schermopname van het deelvenster Project met Maken en Materiaal gemarkeerd. Schermopname van het deelvenster Project. Blauw is gemarkeerd in het deelvenster Materialen.

  6. Als het nieuwe blauwe materiaal is geselecteerd, bekijkt u de Inspector en klikt u op het rechthoekige venster naast Albedo. Selecteer een blauwe kleur (de onderstaande afbeelding is Hex Color: #3592FFFF). Klik op de knop Sluiten zodra u deze hebt gekozen.

    Schermopname van het deelvenster Inspector. De kleursectie is gemarkeerd.

  7. Sleep uw nieuwe materiaal vanuit de map Materialen naar uw zojuist gemaakte vlak in uw scène (of zet het neer op het object Plane in de hiërarchie).

    Schermopname van het deelvenster Scène met het nieuwe materiaal uit de map Materialen.

  8. Klik met de rechtermuisknop in een leeg gebied in het deelvenster Hiërarchie en klik vervolgens op 3D-object, capsule.

    • Terwijl de capsule is geselecteerd, wijzigt u de positie van de transformatie in: -10, 1, 0.
  9. Klik met de rechtermuisknop in een leeg gebied in het deelvenster Hiërarchie en klik vervolgens op 3D-object, kubus.

    • Terwijl de kubus is geselecteerd, wijzigt u de positie van de transformatie in: 0, 0, 10.
  10. Klik met de rechtermuisknop in een leeg gebied in het deelvenster Hiërarchie en klik vervolgens op 3D-object, Sphere.

    • Terwijl de bol is geselecteerd, wijzigt u de positie van de transformatie in: 10, 0, 0.

    Schermopname van de deelvensters Scène, Hiërarchie en Inspector. Capsule is geselecteerd in het deelvenster Hiërarchie.

    Notitie

    Deze positiewaarden zijn suggesties. U kunt de posities van de objecten instellen op wat u wilt, hoewel het voor de gebruiker van de toepassing gemakkelijker is als de afstand tussen objecten zich niet te ver van de camera bevindt.

  11. Wanneer uw toepassing wordt uitgevoerd, moet deze de objecten in de scène kunnen identificeren om dit te bereiken, moeten ze worden gelabeld. Selecteer een van de objecten en klik in het deelvenster Inspector op Tag toevoegen..., waarmee de Inspector wordt verwisseld met het deelvenster Tags & Layers .

    Schermopname van het deelvenster Inspector met de optie Tag toevoegen gemarkeerd. Schermopname van het deelvenster Inspector met tags en lagen gemarkeerd.

  12. Klik op het +-symbool (plusteken) en typ de tagnaam als ObjectInScene.

    Schermopname van het deelvenster Inspector met Tags en lagen geselecteerd. Het dialoogvenster Nieuwe tagnaam is gemarkeerd.

    Waarschuwing

    Als u een andere naam voor uw tag gebruikt, moet u ervoor zorgen dat deze wijziging ook wordt aangebracht in DataFromAnalytics, ObjectTrigger en Gaze, scripts later, zodat uw objecten in uw scène worden gevonden en gedetecteerd.

  13. Nu de tag is gemaakt, moet u deze toepassen op alle drie uw objecten. Houd de Shift-toets in de hiërarchie ingedrukt en klik vervolgens op de capsule, kubus en bol, en klik vervolgens in de Inspector op de vervolgkeuzelijst naast Tag en klik vervolgens op de ObjectInScene-tag die u hebt gemaakt.

    Schermopname van het deelvenster Inspector, een pijl wijst naar Tag. Het menu Zonder vlag toont Niet-gemarkeerd en ObjectInScene is geselecteerd. Schermopname van twee menu's met Maken en Map gemarkeerd.

Hoofdstuk 6: de klasse ApplicationInsightsTracker maken

Het eerste script dat u moet maken, is ApplicationInsightsTracker. Dit is verantwoordelijk voor:

  1. Gebeurtenissen maken op basis van gebruikersinteracties die moeten worden verzonden naar Azure-toepassing Insights.

  2. De juiste gebeurtenisnamen maken, afhankelijk van de interactie van de gebruiker.

  3. Gebeurtenissen verzenden naar het Application Insights Service-exemplaar.

Ga als volgt te werk om deze klasse te maken:

  1. Klik met de rechtermuisknop in het projectvenster en klik vervolgens op Map maken>. Geef de mapscripts een naam.

    Schermopname van het deelvenster Projecten. Het mappictogram Scripts is gemarkeerd in het deelvenster Assets. Schermopname met menuopties waarin de opties Maken en C#-script zijn geselecteerd.

  2. Dubbelklik op de map Scripts om deze te openen. Klik vervolgens in die map met de rechtermuisknop op C#-script maken>. Geef het script de naam ApplicationInsightsTracker.

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

  4. Werk naamruimten boven aan het script bij zodat deze er als volgt uitziet:

        using Microsoft.ApplicationInsights;
        using Microsoft.ApplicationInsights.DataContracts;
        using Microsoft.ApplicationInsights.Extensibility;
        using UnityEngine;
    
  5. Voeg in de klasse de volgende variabelen in:

        /// <summary>
        /// Allows this class to behavior like a singleton
        /// </summary>
        public static ApplicationInsightsTracker Instance;
    
        /// <summary>
        /// Insert your Instrumentation Key here
        /// </summary>
        internal string instrumentationKey = "Insert Instrumentation Key here";
    
        /// <summary>
        /// Insert your Application Id here
        /// </summary>
        internal string applicationId = "Insert Application Id here";
    
        /// <summary>
        /// Insert your API Key here
        /// </summary>
        internal string API_Key = "Insert API Key here";
    
        /// <summary>
        /// Represent the Analytic Custom Event object
        /// </summary>
        private TelemetryClient telemetryClient;
    
        /// <summary>
        /// Represent the Analytic object able to host gaze duration
        /// </summary>
        private MetricTelemetry metric;
    

    Notitie

    Stel de waarden voor instrumentationKey, applicationId en API_Key op de juiste wijze in met behulp van de servicesleutels uit de Azure-portal, zoals vermeld in hoofdstuk 1, stap 9 en hoger.

  6. Voeg vervolgens de Methoden Start() en Awake() toe, die worden aangeroepen wanneer de klasse wordt geïnitialiseerd:

        /// <summary>
        /// Sets this class instance as a singleton
        /// </summary>
        void Awake()
        {
            Instance = this;
        }
    
        /// <summary>
        /// Use this for initialization
        /// </summary>
        void Start()
        {
            // Instantiate telemetry and metric
            telemetryClient = new TelemetryClient();
    
            metric = new MetricTelemetry();
    
            // Assign the Instrumentation Key to the Event and Metric objects
            TelemetryConfiguration.Active.InstrumentationKey = instrumentationKey;
    
            telemetryClient.InstrumentationKey = instrumentationKey;
        }
    
  7. Voeg de methoden toe die verantwoordelijk zijn voor het verzenden van de gebeurtenissen en metrische gegevens die zijn geregistreerd door uw toepassing:

        /// <summary>
        /// Submit the Event to Azure Analytics using the event trigger object
        /// </summary>
        public void RecordProximityEvent(string objectName)
        {
            telemetryClient.TrackEvent(CreateEventName(objectName));
        }
    
        /// <summary>
        /// Uses the name of the object involved in the event to create 
        /// and return an Event Name convention
        /// </summary>
        public string CreateEventName(string name)
        {
            string eventName = $"User near {name}";
            return eventName;
        }
    
        /// <summary>
        /// Submit a Metric to Azure Analytics using the metric gazed object
        /// and the time count of the gaze
        /// </summary>
        public void RecordGazeMetrics(string objectName, int time)
        {
            // Output Console information about gaze.
            Debug.Log($"Finished gazing at {objectName}, which went for <b>{time}</b> second{(time != 1 ? "s" : "")}");
    
            metric.Name = $"Gazed {objectName}";
    
            metric.Value = time;
    
            telemetryClient.TrackMetric(metric);
        }
    
  8. Sla uw wijzigingen op in Visual Studio voordat u terugkeert naar Unity.

Hoofdstuk 7 - Het gazescript maken

Het volgende script dat moet worden gemaakt, is het Gaze-script . Dit script is verantwoordelijk voor het maken van een Raycast die wordt geprojecteerd vanaf de Main Camera, om te detecteren naar welk object de gebruiker kijkt. In dit geval moet de Raycast bepalen of de gebruiker naar een object kijkt met de ObjectInScene-tag en vervolgens tellen hoe lang de gebruiker naar dat object kijkt .

  1. Dubbelklik op de map Scripts om deze te openen.

  2. Klik met de rechtermuisknop in de map Scripts en klik op C#-script maken>. Geef het script de naam Gaze.

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

  4. Vervang de bestaande code door het volgende:

        using UnityEngine;
    
        public class Gaze : MonoBehaviour
        {
            /// <summary>
            /// Provides Singleton-like behavior to this class.
            /// </summary>
            public static Gaze Instance;
    
            /// <summary>
            /// Provides a reference to the object the user is currently looking at.
            /// </summary>
            public GameObject FocusedGameObject { get; private set; }
    
            /// <summary>
            /// Provides whether an object has been successfully hit by the raycast.
            /// </summary>
            public bool Hit { get; private set; }
    
            /// <summary>
            /// Provides a reference to compare whether the user is still looking at 
            /// the same object (and has not looked away).
            /// </summary>
            private GameObject _oldFocusedObject = null;
    
            /// <summary>
            /// Max Ray Distance
            /// </summary>
            private float _gazeMaxDistance = 300;
    
            /// <summary>
            /// Max Ray Distance
            /// </summary>
            private float _gazeTimeCounter = 0;
    
            /// <summary>
            /// The cursor object will be created when the app is running,
            /// this will store its values. 
            /// </summary>
            private GameObject _cursor;
        }
    
  5. Code voor de methoden Awake() en Start() moet nu worden toegevoegd.

        private void Awake()
        {
            // Set this class to behave similar to singleton
            Instance = this;
            _cursor = CreateCursor();
        }
    
        void Start()
        {
            FocusedGameObject = null;
        }
    
        /// <summary>
        /// Create a cursor object, to provide what the user
        /// is looking at.
        /// </summary>
        /// <returns></returns>
        private GameObject CreateCursor()    
        {
            GameObject newCursor = GameObject.CreatePrimitive(PrimitiveType.Sphere);
    
            // Remove the collider, so it does not block raycast.
            Destroy(newCursor.GetComponent<SphereCollider>());
    
            newCursor.transform.localScale = new Vector3(0.1f, 0.1f, 0.1f);
    
            newCursor.GetComponent<MeshRenderer>().material.color = 
            Color.HSVToRGB(0.0223f, 0.7922f, 1.000f);
    
            newCursor.SetActive(false);
            return newCursor;
        }
    
  6. Voeg in de klasse Gaze de volgende code toe in de methode Update() om een Raycast te projecteren en de doeltreffer te detecteren:

        /// <summary>
        /// Called every frame
        /// </summary>
        void Update()
        {
            // Set the old focused gameobject.
            _oldFocusedObject = FocusedGameObject;
    
            RaycastHit hitInfo;
    
            // Initialize Raycasting.
            Hit = Physics.Raycast(Camera.main.transform.position, Camera.main.transform.forward, out hitInfo, _gazeMaxDistance);
    
            // Check whether raycast has hit.
            if (Hit == true)
            {
                // Check whether the hit has a collider.
                if (hitInfo.collider != null)
                {
                    // Set the focused object with what the user just looked at.
                    FocusedGameObject = hitInfo.collider.gameObject;
    
                    // Lerp the cursor to the hit point, which helps to stabilize the gaze.
                    _cursor.transform.position = Vector3.Lerp(_cursor.transform.position, hitInfo.point, 0.6f);
    
                    _cursor.SetActive(true);
                }
                else
                {
                    // Object looked on is not valid, set focused gameobject to null.
                    FocusedGameObject = null;
    
                    _cursor.SetActive(false);
                }
            }
            else
            {
                // No object looked upon, set focused gameobject to null.
                FocusedGameObject = null;
    
                _cursor.SetActive(false);
            }
    
            // Check whether the previous focused object is this same object. If so, reset the focused object.
            if (FocusedGameObject != _oldFocusedObject)
            {
                ResetFocusedObject();
            }
            // If they are the same, but are null, reset the counter. 
            else if (FocusedGameObject == null && _oldFocusedObject == null)
            {
                _gazeTimeCounter = 0;
            }
            // Count whilst the user continues looking at the same object.
            else
            {
                _gazeTimeCounter += Time.deltaTime;
            }
        }
    
  7. Voeg de methode ResetFocusedObject() toe om gegevens naar Application Insights te verzenden wanneer de gebruiker een object heeft bekeken.

        /// <summary>
        /// Reset the old focused object, stop the gaze timer, and send data if it
        /// is greater than one.
        /// </summary>
        public void ResetFocusedObject()
        {
            // Ensure the old focused object is not null.
            if (_oldFocusedObject != null)
            {
                // Only looking for objects with the correct tag.
                if (_oldFocusedObject.CompareTag("ObjectInScene"))
                {
                    // Turn the timer into an int, and ensure that more than zero time has passed.
                    int gazeAsInt = (int)_gazeTimeCounter;
    
                    if (gazeAsInt > 0)
                    {
                        //Record the object gazed and duration of gaze for Analytics
                        ApplicationInsightsTracker.Instance.RecordGazeMetrics(_oldFocusedObject.name, gazeAsInt);
                    }
                    //Reset timer
                    _gazeTimeCounter = 0;
                }
            }
        }
    
  8. U hebt nu het gazescript voltooid. Sla uw wijzigingen op in Visual Studio voordat u terugkeert naar Unity.

Hoofdstuk 8: de klasse ObjectTrigger maken

Het volgende script dat u moet maken, is ObjectTrigger, die verantwoordelijk is voor:

  • Onderdelen toevoegen die nodig zijn voor botsing met de hoofdcamera.
  • Detecteren of de camera zich in de buurt van een object bevindt dat is gelabeld als ObjectInScene.

Het script maken:

  1. Dubbelklik op de map Scripts om deze te openen.

  2. Klik met de rechtermuisknop in de map Scripts en klik op C#-script maken>. Geef het script de naam ObjectTrigger.

  3. Dubbelklik op het script om het te openen met Visual Studio. Vervang de bestaande code door het volgende:

        using UnityEngine;
    
        public class ObjectTrigger : MonoBehaviour
        {
            private void Start()
            {
                // Add the Collider and Rigidbody components, 
                // and set their respective settings. This allows for collision.
                gameObject.AddComponent<SphereCollider>().radius = 1.5f;
    
                gameObject.AddComponent<Rigidbody>().useGravity = false;
            }
    
            /// <summary>
            /// Triggered when an object with a collider enters this objects trigger collider.
            /// </summary>
            /// <param name="collision">Collided object</param>
            private void OnCollisionEnter(Collision collision)
            {
                CompareTriggerEvent(collision, true);
            }
    
            /// <summary>
            /// Triggered when an object with a collider exits this objects trigger collider.
            /// </summary>
            /// <param name="collision">Collided object</param>
            private void OnCollisionExit(Collision collision)
            {
                CompareTriggerEvent(collision, false);
            }
    
            /// <summary>
            /// Method for providing debug message, and sending event information to InsightsTracker.
            /// </summary>
            /// <param name="other">Collided object</param>
            /// <param name="enter">Enter = true, Exit = False</param>
            private void CompareTriggerEvent(Collision other, bool enter)
            {
                if (other.collider.CompareTag("ObjectInScene"))
                {
                    string message = $"User is{(enter == true ? " " : " no longer ")}near <b>{other.gameObject.name}</b>";
    
                    if (enter == true)
                    {
                        ApplicationInsightsTracker.Instance.RecordProximityEvent(other.gameObject.name);
                    }
                    Debug.Log(message);
                }
            }
        }
    
  4. Sla uw wijzigingen op in Visual Studio voordat u terugkeert naar Unity.

Hoofdstuk 9: de klasse DataFromAnalytics maken

U moet nu het DataFromAnalytics-script maken. Dit is verantwoordelijk voor:

  • Het ophalen van analysegegevens over welk object het meest door de camera is benaderd.
  • Gebruik de servicesleutels om communicatie met uw Azure-toepassing Insights Service-exemplaar mogelijk te maken.
  • Sorteer de objecten in de scène, afhankelijk van het hoogste aantal gebeurtenissen.
  • Het wijzigen van de materiaalkleur, van het meest benaderde object, in groen.

Het script maken:

  1. Dubbelklik op de map Scripts om deze te openen.

  2. Klik met de rechtermuisknop in de map Scripts en klik op C#-script maken>. Noem het script DataFromAnalytics.

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

  4. Voeg de volgende naamruimten in:

        using Newtonsoft.Json;
        using System;
        using System.Collections;
        using System.Collections.Generic;
        using System.Linq;
        using UnityEngine;
        using UnityEngine.Networking;
    
  5. Voeg in het script het volgende in:

        /// <summary>
        /// Number of most recent events to be queried
        /// </summary>
        private int _quantityOfEventsQueried = 10;
    
        /// <summary>
        /// The timespan with which to query. Needs to be in hours.
        /// </summary>
        private int _timepspanAsHours = 24;
    
        /// <summary>
        /// A list of the objects in the scene
        /// </summary>
        private List<GameObject> _listOfGameObjectsInScene;
    
        /// <summary>
        /// Number of queries which have returned, after being sent.
        /// </summary>
        private int _queriesReturned = 0;
    
        /// <summary>
        /// List of GameObjects, as the Key, with their event count, as the Value.
        /// </summary>
        private List<KeyValuePair<GameObject, int>> _pairedObjectsWithEventCount = new List<KeyValuePair<GameObject, int>>();
    
        // Use this for initialization
        void Start()
        {
            // Find all objects in scene which have the ObjectInScene tag (as there may be other GameObjects in the scene which you do not want).
            _listOfGameObjectsInScene = GameObject.FindGameObjectsWithTag("ObjectInScene").ToList();
    
            FetchAnalytics();
        }
    
  6. Voeg in de klasse DataFromAnalytics, direct na de Methode Start(), de volgende methode toe met de naam FetchAnalytics(). Deze methode is verantwoordelijk voor het vullen van de lijst met sleutelwaardeparen, met een GameObject en een aantal tijdelijke aanduidingen voor het aantal gebeurtenissen. Vervolgens wordt de GetWebRequest() coroutine geïnitialiseerd. De querystructuur van de aanroep naar Application Insights vindt u ook in deze methode, als het eindpunt van de query-URL .

        private void FetchAnalytics()
        {
            // Iterate through the objects in the list
            for (int i = 0; i < _listOfGameObjectsInScene.Count; i++)
            {
                // The current event number is not known, so set it to zero.
                int eventCount = 0;
    
                // Add new pair to list, as placeholder, until eventCount is known.
                _pairedObjectsWithEventCount.Add(new KeyValuePair<GameObject, int>(_listOfGameObjectsInScene[i], eventCount));
    
                // Set the renderer of the object to the default color, white
                _listOfGameObjectsInScene[i].GetComponent<Renderer>().material.color = Color.white;
    
                // Create the appropriate object name using Insights structure
                string objectName = _listOfGameObjectsInScene[i].name;
    
     		    // Build the queryUrl for this object.
     		    string queryUrl = Uri.EscapeUriString(string.Format(
                    "https://api.applicationinsights.io/v1/apps/{0}/events/$all?timespan=PT{1}H&$search={2}&$select=customMetric/name&$top={3}&$count=true",
     			    ApplicationInsightsTracker.Instance.applicationId, _timepspanAsHours, "Gazed " + objectName, _quantityOfEventsQueried));
    
    
                // Send this object away within the WebRequest Coroutine, to determine it is event count.
                StartCoroutine("GetWebRequest", new KeyValuePair<string, int>(queryUrl, i));
            }
        }
    
  7. Voeg onder de methode FetchAnalytics() een methode toe met de naam GetWebRequest(), die een IEnumerator retourneert. Deze methode is verantwoordelijk voor het aanvragen van het aantal keren dat een gebeurtenis, die overeenkomt met een specifiek GameObject, is aangeroepen in Application Insights. Wanneer alle verzonden query's zijn geretourneerd, wordt de methode DetermineWinner() aangeroepen.

        /// <summary>
        /// Requests the data count for number of events, according to the
        /// input query URL.
        /// </summary>
        /// <param name="webQueryPair">Query URL and the list number count.</param>
        /// <returns></returns>
        private IEnumerator GetWebRequest(KeyValuePair<string, int> webQueryPair)
        {
            // Set the URL and count as their own variables (for readability).
            string url = webQueryPair.Key;
            int currentCount = webQueryPair.Value;
    
            using (UnityWebRequest unityWebRequest = UnityWebRequest.Get(url))
            {
                DownloadHandlerBuffer handlerBuffer = new DownloadHandlerBuffer();
    
                unityWebRequest.downloadHandler = handlerBuffer;
    
                unityWebRequest.SetRequestHeader("host", "api.applicationinsights.io");
    
                unityWebRequest.SetRequestHeader("x-api-key", ApplicationInsightsTracker.Instance.API_Key);
    
                yield return unityWebRequest.SendWebRequest();
    
                if (unityWebRequest.isNetworkError)
                {
                    // Failure with web request.
                    Debug.Log("<color=red>Error Sending:</color> " + unityWebRequest.error);
                }
                else
                {
                    // This query has returned, so add to the current count.
                    _queriesReturned++;
    
                    // Initialize event count integer.
                    int eventCount = 0;
    
                    // Deserialize the response with the custom Analytics class.
                    Analytics welcome = JsonConvert.DeserializeObject<Analytics>(unityWebRequest.downloadHandler.text);
    
                    // Get and return the count for the Event
                    if (int.TryParse(welcome.OdataCount, out eventCount) == false)
                    {
                        // Parsing failed. Can sometimes mean that the Query URL was incorrect.
                        Debug.Log("<color=red>Failure to Parse Data Results. Check Query URL for issues.</color>");
                    }
                    else
                    {
                        // Overwrite the current pair, with its actual values, now that the event count is known.
                        _pairedObjectsWithEventCount[currentCount] = new KeyValuePair<GameObject, int>(_pairedObjectsWithEventCount[currentCount].Key, eventCount);
                    }
    
                    // If all queries (compared with the number which was sent away) have 
                    // returned, then run the determine winner method. 
                    if (_queriesReturned == _pairedObjectsWithEventCount.Count)
                    {
                        DetermineWinner();
                    }
                }
            }
        }
    
  8. De volgende methode is DetermineWinner(), waarmee de lijst met GameObject- en Int-paren wordt gesorteerd op basis van het hoogste aantal gebeurtenissen. Vervolgens verandert de materiaalkleur van dat GameObject in groen (als feedback voor het hebben van het hoogste aantal). Hiermee wordt een bericht met de analyseresultaten weergegeven.

        /// <summary>
        /// Call to determine the keyValue pair, within the objects list, 
        /// with the highest event count.
        /// </summary>
        private void DetermineWinner()
        {
            // Sort the values within the list of pairs.
            _pairedObjectsWithEventCount.Sort((x, y) => y.Value.CompareTo(x.Value));
    
            // Change its colour to green
            _pairedObjectsWithEventCount.First().Key.GetComponent<Renderer>().material.color = Color.green;
    
            // Provide the winner, and other results, within the console window. 
            string message = $"<b>Analytics Results:</b>\n " +
                $"<i>{_pairedObjectsWithEventCount.First().Key.name}</i> has the highest event count, " +
                $"with <i>{_pairedObjectsWithEventCount.First().Value.ToString()}</i>.\nFollowed by: ";
    
            for (int i = 1; i < _pairedObjectsWithEventCount.Count; i++)
            {
                message += $"{_pairedObjectsWithEventCount[i].Key.name}, " +
                    $"with {_pairedObjectsWithEventCount[i].Value.ToString()} events.\n";
            }
    
            Debug.Log(message);
        }
    
  9. Voeg de klassestructuur toe die wordt gebruikt om het JSON-object te deserialiseren, ontvangen van Application Insights. Voeg deze klassen onder aan uw DataFromAnalytics-klassebestand toe, buiten de klassedefinitie.

        /// <summary>
        /// These classes represent the structure of the JSON response from Azure Insight
        /// </summary>
        [Serializable]
        public class Analytics
        {
            [JsonProperty("@odata.context")]
            public string OdataContext { get; set; }
    
            [JsonProperty("@odata.count")]
            public string OdataCount { get; set; }
    
            [JsonProperty("value")]
            public Value[] Value { get; set; }
        }
    
        [Serializable]
        public class Value
        {
            [JsonProperty("customMetric")]
            public CustomMetric CustomMetric { get; set; }
        }
    
        [Serializable]
        public class CustomMetric
        {
            [JsonProperty("name")]
            public string Name { get; set; }
        }
    
  10. Sla uw wijzigingen op in Visual Studio voordat u terugkeert naar Unity.

Hoofdstuk 10 - De klasse Beweging maken

Het script Movement is het volgende script dat u moet maken. Het is verantwoordelijk voor:

  • Het verplaatsen van de hoofdcamera volgens de richting waarnaar de camera kijkt.
  • Alle andere scripts toevoegen aan scèneobjecten.

Het script maken:

  1. Dubbelklik op de map Scripts om deze te openen.

  2. Klik met de rechtermuisknop in de map Scripts en klik op C#-script maken>. Noem de scriptverplaatsing.

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

  4. Vervang de bestaande code door het volgende:

        using UnityEngine;
        using UnityEngine.XR.WSA.Input;
    
        public class Movement : MonoBehaviour
        {
            /// <summary>
            /// The rendered object representing the right controller.
            /// </summary>
            public GameObject Controller;
    
            /// <summary>
            /// The movement speed of the user.
            /// </summary>
            public float UserSpeed;
    
            /// <summary>
            /// Provides whether source updates have been registered.
            /// </summary>
            private bool _isAttached = false;
    
            /// <summary>
            /// The chosen controller hand to use. 
            /// </summary>
            private InteractionSourceHandedness _handness = InteractionSourceHandedness.Right;
    
            /// <summary>
            /// Used to calculate and proposes movement translation.
            /// </summary>
            private Vector3 _playerMovementTranslation;
    
            private void Start()
            {
                // You are now adding components dynamically 
                // to ensure they are existing on the correct object  
    
                // Add all camera related scripts to the camera. 
                Camera.main.gameObject.AddComponent<Gaze>();
                Camera.main.gameObject.AddComponent<ObjectTrigger>();
    
                // Add all other scripts to this object.
                gameObject.AddComponent<ApplicationInsightsTracker>();
                gameObject.AddComponent<DataFromAnalytics>();
            }
    
            // Update is called once per frame
            void Update()
            {
    
            }
        }
    
  5. Voeg in de klasse Movement onder de lege Methode Update() de volgende methoden in waarmee de gebruiker de handcontroller kan gebruiken om in de virtuele ruimte te navigeren:

        /// <summary>
        /// Used for tracking the current position and rotation of the controller.
        /// </summary>
        private void UpdateControllerState()
        {
    #if UNITY_WSA && UNITY_2017_2_OR_NEWER
            // Check for current connected controllers, only if WSA.
            string message = string.Empty;
    
            if (InteractionManager.GetCurrentReading().Length > 0)
            {
                foreach (var sourceState in InteractionManager.GetCurrentReading())
                {
                    if (sourceState.source.kind == InteractionSourceKind.Controller && sourceState.source.handedness == _handness)
                    {
                        // If a controller source is found, which matches the selected handness, 
                        // check whether interaction source updated events have been registered. 
                        if (_isAttached == false)
                        {
                            // Register events, as not yet registered.
                            message = "<color=green>Source Found: Registering Controller Source Events</color>";
                            _isAttached = true;
    
                            InteractionManager.InteractionSourceUpdated += InteractionManager_InteractionSourceUpdated;
                        }
    
                        // Update the position and rotation information for the controller.
                        Vector3 newPosition;
                        if (sourceState.sourcePose.TryGetPosition(out newPosition, InteractionSourceNode.Pointer) && ValidPosition(newPosition))
                        {
                            Controller.transform.localPosition = newPosition;
                        }
    
                        Quaternion newRotation;
    
                        if (sourceState.sourcePose.TryGetRotation(out newRotation, InteractionSourceNode.Pointer) && ValidRotation(newRotation))
                        {
                            Controller.transform.localRotation = newRotation;
                        }
                    }
                }
            }
            else
            {
                // Controller source not detected. 
                message = "<color=blue>Trying to detect controller source</color>";
    
                if (_isAttached == true)
                {
                    // A source was previously connected, however, has been lost. Disconnected
                    // all registered events. 
    
                    _isAttached = false;
    
                    InteractionManager.InteractionSourceUpdated -= InteractionManager_InteractionSourceUpdated;
    
                    message = "<color=red>Source Lost: Detaching Controller Source Events</color>";
                }
            }
    
            if(message != string.Empty)
            {
                Debug.Log(message);
            }
    #endif
        }
    
        /// <summary>
        /// This registered event is triggered when a source state has been updated.
        /// </summary>
        /// <param name="obj"></param>
        private void InteractionManager_InteractionSourceUpdated(InteractionSourceUpdatedEventArgs obj)
        {
            if (obj.state.source.handedness == _handness)
            {
                if(obj.state.thumbstickPosition.magnitude > 0.2f)
                {
                    float thumbstickY = obj.state.thumbstickPosition.y;
    
                    // Vertical Input.
                    if (thumbstickY > 0.3f || thumbstickY < -0.3f)
                    {
                        _playerMovementTranslation = Camera.main.transform.forward;
                        _playerMovementTranslation.y = 0;
                        transform.Translate(_playerMovementTranslation * UserSpeed * Time.deltaTime * thumbstickY, Space.World);
                    }
                }
            }
        }
    
        /// <summary>
        /// Check that controller position is valid. 
        /// </summary>
        /// <param name="inputVector3">The Vector3 to check</param>
        /// <returns>The position is valid</returns>
        private bool ValidPosition(Vector3 inputVector3)
        {
            return !float.IsNaN(inputVector3.x) && !float.IsNaN(inputVector3.y) && !float.IsNaN(inputVector3.z) && !float.IsInfinity(inputVector3.x) && !float.IsInfinity(inputVector3.y) && !float.IsInfinity(inputVector3.z);
        }
    
        /// <summary>
        /// Check that controller rotation is valid. 
        /// </summary>
        /// <param name="inputQuaternion">The Quaternion to check</param>
        /// <returns>The rotation is valid</returns>
        private bool ValidRotation(Quaternion inputQuaternion)
        {
            return !float.IsNaN(inputQuaternion.x) && !float.IsNaN(inputQuaternion.y) && !float.IsNaN(inputQuaternion.z) && !float.IsNaN(inputQuaternion.w) && !float.IsInfinity(inputQuaternion.x) && !float.IsInfinity(inputQuaternion.y) && !float.IsInfinity(inputQuaternion.z) && !float.IsInfinity(inputQuaternion.w);
        }   
    
  6. Voeg tot slot de methode-aanroep toe binnen de methode Update( ).

        // Update is called once per frame
        void Update()
        {
            UpdateControllerState();
        }
    
  7. Sla uw wijzigingen op in Visual Studio voordat u terugkeert naar Unity.

Hoofdstuk 11 - De scriptsverwijzingen instellen

In dit hoofdstuk moet u het bewegingsscript op de bovenliggende camera plaatsen en de referentiedoelen instellen. Dat script verwerkt vervolgens het plaatsen van de andere scripts waar ze moeten zijn.

  1. Sleep vanuit de map Scripts in het projectvenster het verplaatsingsscript naar het bovenliggende object Camera, dat zich in het deelvenster Hiërarchie bevindt.

    Schermopname van de deelvensters Project en Hiërarchie. Beweging is gemarkeerd.

  2. Klik op de bovenliggende camera. Sleep in het deelvenster Hiërarchie het object Rechts van het deelvenster Hierarchy naar het referentiedoel, Controller, in het Inspector Panel. Stel de gebruikerssnelheid in op 5, zoals wordt weergegeven in de onderstaande afbeelding.

    Schermopname van de deelvensters Hiërarchie en Inspector. Een lijn verbindt rechterhand op beide panelen.

Hoofdstuk 12 - Het Unity-project bouwen

Alles wat nodig is voor de Unity-sectie van dit project is nu voltooid, dus het is tijd om het te bouwen vanuit Unity.

  1. Navigeer naar Build-instellingen (Instellingen voor bestandsbuild>).

  2. Klik in het venster Build-instellingen op Build.

    Schermopname van het venster Build-instellingen met Scènes in build.

  3. Er wordt een Bestandenverkenner venster weergegeven waarin u wordt gevraagd om een locatie voor de build. Maak een nieuwe map (door te klikken op Nieuwe map in de linkerbovenhoek) en geef deze de naam BUILDS.

    Schermopname van Bestandenverkenner met de map Builds gemarkeerd.

    1. Open de nieuwe map BUILDS en maak nog een map (met nieuwe map ) en geef deze MR_Azure_Application_Insights een naam.

      Schermopname van Verkenner met de map MR_Azure_Insights.

    2. Klik op Map selecteren als de MR_Azure_Application_Insights map is geselecteerd. Het duurt ongeveer een minuut voordat het project is gebouwd.

  4. Na Build wordt Bestandenverkenner weergegeven met de locatie van uw nieuwe project.

Hoofdstuk 13- MR_Azure_Application_Insights-app implementeren op uw computer

De MR_Azure_Application_Insights-app implementeren op uw lokale computer:

  1. Open het oplossingsbestand van uw MR_Azure_Application_Insights-app in Visual Studio.

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

  3. Selecteer foutopsporing in de oplossingsconfiguratie.

    Schermopname van het scherm Visual Studio Solution Configuration met Foutopsporing in de menubalk.

  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 die klaar zijn om te worden gestart.

  6. Start de mixed reality-toepassing.

  7. Navigeer door de scène, naderende objecten en bekijk ze, wanneer de Azure Insight Service voldoende gebeurtenisgegevens heeft verzameld, wordt het object ingesteld dat het meest groen is benaderd.

Belangrijk

Hoewel de gemiddelde wachttijd voor de gebeurtenissen en metrische gegevens die door de service moeten worden verzameld ongeveer 15 minuten duurt, kan het in sommige gevallen tot 1 uur duren.

Hoofdstuk 14 - De Application Insights Service-portal

Zodra u rond de scène hebt geroerd en naar verschillende objecten hebt gekeken, kunt u de gegevens zien die zijn verzameld in de Application Insights Service-portal .

  1. Ga terug naar uw Application Insights Service-portal.

  2. Selecteer Metrics Explorer.

    Schermopname van het deelvenster MyNewInsight met de lijst met opties. Metrics Explorer wordt weergegeven in de sectie Onderzoeken.

  3. Het wordt geopend op een tabblad met de grafiek, dat de gebeurtenissen en metrische gegevens vertegenwoordigt die betrekking hebben op uw toepassing. Zoals hierboven vermeld, kan het enige tijd duren (maximaal 1 uur) voordat de gegevens in de grafiek worden weergegeven

    Schermopname van Metrics Explorer met de grafiek met gebeurtenissen en metrische gegevens.

  4. Selecteer de gebeurtenissenbalk in het totaal van gebeurtenissen per toepassingsversie om een gedetailleerde uitsplitsing van de gebeurtenissen met hun namen te bekijken.

    Schermopname van het deelvenster Zoeken met de resultaten van een aangepast gebeurtenisfilter.

Uw Toepassing application Application Insights Service is voltooid

Gefeliciteerd, u hebt een mixed reality-app gemaakt die gebruikmaakt van de Application Insights-service om de activiteiten van gebruikers in uw app te bewaken.

Welkomstscherm cursus.

Bonusoefeningen

Oefening 1

Probeer te spawning, in plaats van handmatig te maken, de ObjectInScene-objecten en stel de coördinaten in het vlak in uw scripts in. Op deze manier kunt u Azure vragen wat het populairste object was (van staren of nabijheidsresultaten) en een extra van deze objecten spawnen.

Oefening 2

Sorteer uw Application Insights-resultaten op tijd, zodat u de meest relevante gegevens krijgt en die tijdgevoelige gegevens in uw toepassing implementeert.