Delen via


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

Opmerking

De zelfstudies van Mixed Reality Academy zijn ontworpen met HoloLens (1e generatie) en Mixed Reality Immersive Headsets in gedachten. Daarom vinden we het belangrijk om deze zelfstudies te laten staan voor ontwikkelaars die nog steeds op zoek zijn naar hulp bij het ontwikkelen van deze apparaten. Deze zelfstudies worden niet bijgewerkt met de nieuwste hulpprogramma's of interacties die worden gebruikt voor HoloLens 2. Ze worden onderhouden om te blijven werken op de ondersteunde apparaten. Er zal in de toekomst een nieuwe reeks zelfstudies worden gepost die laten zien hoe u kunt ontwikkelen voor HoloLens 2. Deze kennisgeving wordt bijgewerkt met een koppeling naar die zelfstudies wanneer ze worden geplaatst.

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 Azure-toepassing Insights-API om analyses met betrekking tot gebruikersgedrag te verzamelen.

Application Insights is een Microsoft-service waarmee ontwikkelaars analyses van hun toepassingen kunnen verzamelen en deze kunnen beheren vanuit een gebruiksvriendelijke portal. De analyse kan van alles zijn, van prestaties tot aangepaste informatie die u wilt verzamelen. Ga naar de pagina Application Insights voor meer informatie.

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

  1. Sta de gebruiker toe om een scène te staren en te verplaatsen.
  2. Activeer het verzenden van analyses naar de Application Insights-service met behulp van Starze en Proximity voor objecten in scènes.
  3. De app roept ook de Service aan en haalt informatie op over welk object het meest is benaderd door de gebruiker, in de afgelopen 24 uur. Dat object verandert 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.

Apparaatondersteuning

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

Opmerking

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

Voorwaarden

Opmerking

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

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

Voordat u van start gaat

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

Waarschuwing

Houd er rekening mee dat gegevens die naar Application Insights gaan, tijd kosten, dus wees geduldig. Als u wilt controleren of de Service uw gegevens heeft ontvangen, raadpleegt u Hoofdstuk 14, waarin wordt uitgelegd 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 de Azure Portal.

  1. Meld u aan bij Azure Portal.

    Opmerking

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

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

    Opmerking

    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 bevat 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 scherm Application Insights, Maken is gemarkeerd.

  4. Nadat u op Maken hebt geklikt:

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

    2. SelecteerAlgemeen als Toepassingstype.

    3. Selecteer een geschikt abonnement.

    4. Kies een resourcegroep of maak een nieuwe. Een resourcegroep biedt een manier om een verzameling Azure-assets te bewaken, de toegang te beheren, de facturering in te richten en te beheren. Het is raadzaam om alle Azure-services die zijn gekoppeld aan één project (bijvoorbeeld deze cursussen) onder een gemeenschappelijke resourcegroep te houden.

      Als u meer wilt lezen 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 op deze Service van toepassing zijn.

    7. Selecteer Maken.

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

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

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

    Schermopname van een deel 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 resource is gemarkeerd.

  8. Klik op de knop Ga naar 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 met de naam van het exemplaar MyNewInsight.

    Opmerking

    Houd deze webpagina geopend en gemakkelijk toegankelijk. U komt hier vaak terug om de verzamelde gegevens te bekijken.

    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 kunt ophalen uit uw Service. Noteer deze waarden op een lege Kladblok-pagina , omdat u ze 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. Onder Eigenschappen vindt u API-toegang, waarop u moet klikken. In het deelvenster aan de rechterkant wordt de toepassings-id van uw app weergegeven.

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

  11. Terwijl het deelvenster Toepassings-id nog steeds is geopend, klikt u op API-sleutel maken. Het deelvenster API-sleutel maken wordt geopend.

    Schermopname van het toetsvenster A P I maken.

  12. Typ in het nu geopende deelvenster API-sleutel maken een beschrijving en vink de drie vakjes aan.

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

    Schermopname van het deelvenster A P I-sleutel maken met de nieuwe servicesleutelgegevens.

    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

Het volgende is een typische installatie voor het ontwikkelen met de mixed reality en is als zodanig 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 en MR_Azure_Application_Insights invoegen. Zorg ervoor dat de sjabloon is ingesteld op 3D. Stel de locatie in op een geschikte locatie (dichter bij hoofdmappen is beter). Klik vervolgens op Project maken.

    Schermopname van het venster Nieuwe projecten van Unity, met projectgegevens.

  3. Als Unity is geopend, is het de moeite waard om te controleren of de standaardscript-Editor is ingesteld op Visual Studio. Ga naar Voorkeuren bewerken > en navigeer vervolgens vanuit het nieuwe venster naar Externe hulpprogramma's. Wijzig extern script Editor 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-instellingen, met de selectielijst Platform. Universeel Windows-platform is geselecteerd.

  5. Ga naar Instellingen voor bestandsopbouw > 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. Dit doet u door Open scènes toevoegen te selecteren. Er wordt een venster voor opslaan weergegeven.

        Schermopname van het venster Build-instellingen, Geopende scènes toevoegen is geselecteerd.

      2. Maak hiervoor een nieuwe map en een eventuele toekomstige scène en klik vervolgens op de knop Nieuwe map om een nieuwe map te maken en 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 typ in het tekstveld Bestandsnaam:ApplicationInsightsScene en klik vervolgens op Opslaan.

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

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

  7. Selecteer in het venster Build-instellingende optie Instellingen voor speler. Hiermee wordt het gerelateerde deelvenster geopend in de ruimte waar de Inspector zich bevindt.

    Schermopname van het tabblad Inspector met spelerinstellingen.

  8. In dit deelvenster moeten enkele instellingen worden geverifieerd:

    1. Op het tabblad Overige instellingen :

      1. ScriptingRuntime-versie moet Experimenteel (.NET 4.6 Equivalent) zijn, waardoor de Editor opnieuw moet worden gestart.

      2. De back-end van 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. Controleer op het tabblad Publicatie-instellingen onder Mogelijkheden het volgende:

      • InternetClient

        Schermopname van de lijst Mogelijkheden, internetclient is ingeschakeld.

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

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

  9. Terug in build-instellingen wordt Unity C# Projects niet langer grijs weergegeven; schakel het selectievakje naast dit selectievakje in.

  10. Sluit het venster Build-instellingen.

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

Hoofdstuk 3- Het Unity-pakket importeren

Belangrijk

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

Belangrijk

Als u Application Insights in Unity wilt gebruiken, moet u de DLL ervoor importeren, samen met de Newtonsoft-DLL. Er is momenteel een bekend probleem in Unity waardoor invoegtoepassingen na het importeren opnieuw moeten worden geconfigureerd. Deze stappen (4 - 7 in deze sectie) zijn niet meer vereist nadat de fout is opgelost.

Als u Application Insights wilt importeren in uw eigen project, moet u ervoor zorgen dat u het '.unitypackage' met de invoegtoepassingen hebt gedownload. Ga vervolgens als volgt te werk:

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

  2. Controleer in het vak Unity-pakket importeren dat wordt weergegeven of alles onder (en inclusief) Invoegtoepassingen is geselecteerd.

    Schermopname van het dialoogvenster Import Unity Package met alle items die zijn ingeschakeld.

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

  4. Ga in de projectweergave naar de map Inzichten onder Invoegtoepassingen 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 Elk platform is uitgeschakeld, 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 Zelfstandig ingeschakeld.

    Opmerking

    Als u de invoegtoepassingen op deze wijze markeert, configureert u ze om ze alleen te gebruiken in de Unity-Editor. De WSA-map bevat een andere set DLL's die wordt gebruikt nadat het project uit Unity is geëxporteerd.

  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 in de inspector of Any Platform is uitgeschakeld en zorg er vervolgens voor dat alleenWSAPlayer 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 invoegtoepassingsselecties.

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 erin kan bewegen.

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

    Schermopname van het deelvenster Hiërarchie, Leeg maken is geselecteerd.

  2. Wijzig de naam van het nieuwe lege GameObject in Bovenliggende camera.

    Schermopname van het deelvenster Hiërarchie met Bovenliggende camera geselecteerd. Het deelvenster Inspector

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

  4. Wijzig de naam van de bol in 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 onderdeel Sphere Collider uit de rechterhand door te klikken op het tandwiel in het onderdeel Sphere Collider en vervolgens Onderdeel verwijderen.

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

  7. Sleep in het deelvenster Hiërarchie de objecten Hoofdcamera en rechterhand naar het bovenliggende object Camera .

    Schermopname van het deelvenster Hiërarchie met hoofdcamera geselecteerd. In het deelvenster Inspector ziet u Hoofdcamera ingeschakeld.

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

    Schermopname van het deelvenster Hiërarchie met Hoofdcamera geselecteerd, Transformatie-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 maakt nu enkele basisvormen voor uw scène, waarmee de gebruiker kan communiceren.

  1. Klik met de rechtermuisknop in een leeg gebied in het deelvenster Hiërarchie, klik vervolgens op 3D-object en selecteer vervolgens 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 vormen beter zichtbaar zijn. Navigeer naar het projectvenster, 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 is gemarkeerd in het deelvenster Activa.

  5. Open de map Materialen , 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, kijkt u naar de Inspector en klikt u op het rechthoekige venster naast Albedo. Selecteer een blauwe kleur (de enige afbeelding hieronder is HexKleur: #3592FFFF). Klik op de knop Sluiten zodra u hebt gekozen.

    Schermopname van het deelvenster Inspector. De kleursectie is gemarkeerd.

  7. Sleep het nieuwe materiaal vanuit de map Materialen naar het 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 transformatiepositie 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 transformatiepositie 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 transformatiepositie in: 10, 0, 0.

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

    Opmerking

    Deze positiewaarden zijn suggesties. U bent vrij om de positie van de objecten in te stellen op wat u wilt, maar het is gemakkelijker voor de gebruiker van de toepassing als de objecten niet te ver van de camera verwijderd zijn.

  11. Wanneer uw toepassing wordt uitgevoerd, moet deze de objecten in de scène kunnen identificeren. Hiervoor moeten ze worden getagd. Selecteer een van de objecten en klik in het deelvenster Inspector op Tag toevoegen... om de Inspector te vervangen door het deelvenster Tags & Lagen .

    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 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 later ook wordt doorgevoerd in de scripts DataFromAnalytics, ObjectTrigger en Gaze, zodat uw objecten in uw scène worden gevonden en gedetecteerd.

  13. Nu de tag is gemaakt, moet u deze nu toepassen op alle drie uw objecten. Houd in de hiërarchie de Shift-toets ingedrukt, klik vervolgens op de objecten Capsule, Kubus en Bol, en klik in de Inspector op het vervolgkeuzemenu naast Tag en klik vervolgens op de tag ObjectInScene die u hebt gemaakt.

    Schermopname van het deelvenster Inspector, een pijl wijst naar Tag. In het menu Zonder vlag wordt Untagged ingeschakeld weergegeven en Is ObjectInScene 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, dat verantwoordelijk is voor:

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

  2. De juiste gebeurtenisnamen maken, afhankelijk van gebruikersinteractie.

  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 map de naam Scripts.

    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 de map te openen. Klik vervolgens in die map met de rechtermuisknop opC#-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;
    

    Opmerking

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

  6. Voeg vervolgens de methoden Start() en Awake() toe. Deze 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 door uw toepassing zijn geregistreerd:

        /// <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 Gaze-script 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 hoofdcamera, om te detecteren welk object de gebruiker bekijkt. In dit geval moet de Raycast bepalen of de gebruiker naar een object kijkt met de tag ObjectInScene en vervolgens tellen hoe lang de gebruiker naar dat object staart .

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

  2. Klik met de rechtermuisknop in de map Scripts en klik opC#-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 Gaze-script 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, dat verantwoordelijk is voor:

  • Onderdelen die nodig zijn voor botsingen toevoegen aan de hoofdcamera.
  • Detecteren of de camera zich in de buurt van een object bevindt dat is getagd 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 opC#-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 script DataFromAnalytics maken, dat verantwoordelijk is voor:

  • Analytische gegevens ophalen over welk object het meest is benaderd door de camera.
  • Met behulp van de servicesleutels, waarmee communicatie met uw Azure-toepassing Insights Service-exemplaar mogelijk is.
  • De objecten sorteren in scène, op basis waarvan het hoogste aantal gebeurtenissen is.
  • De materiaalkleur van het meest benaderde object wijzigen 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 opC#-script maken>. Geef het script de naam 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 het volgende in het script 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 met de naam FetchAnalytics() toe. Deze methode is verantwoordelijk voor het vullen van de lijst met sleutelwaardeparen, met een GameObject en een tijdelijke aanduiding voor het aantal gebeurtenissen. Vervolgens wordt de coroutine GetWebRequest() geïnitialiseerd. De querystructuur van de aanroep van Application Insights is ook te vinden 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 direct 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 van GameObject - en Int-paren wordt gesorteerd op basis van het hoogste aantal gebeurtenissen. Vervolgens wordt de materiaalkleur van dat GameObject gewijzigd in groen (als feedback voor het hoogste aantal). Hiermee wordt een bericht weergegeven met de analyseresultaten.

        /// <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 dat is ontvangen van Application Insights, te deserialiseren. Voeg deze klassen helemaal onder aan het klassebestand DataFromAnalytics 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 Movement maken

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

  • De hoofdcamera verplaatsen 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 opC#-script maken>. Geef het script de naam Movement.

  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 zich in de virtuele ruimte te verplaatsen:

        /// <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 ten slotte 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 scripts-verwijzingen instellen

In dit hoofdstuk moet u het bewegingsscript op de bovenliggende camera plaatsen en de referentiedoelen instellen. Dat script zorgt er vervolgens voor dat de andere scripts worden geplaatst waar ze moeten zijn.

  1. Sleep vanuit de map Scripts in het deelvenster Project 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 Hiërarchie naar het referentiedoel, Controller, in het deelvenster Inspector. 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. Ga naar Build-instellingen(Instellingenvoor bestandsbuilding>).

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

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

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

    Schermopname van Bestandenverkenner met de map Builds gemarkeerd.

    1. Open de nieuwe map BUILDS en maak een andere map (opnieuw met behulp van Nieuwe map ) en geef deze de naam MR_Azure_Application_Insights.

      Schermopname van Verkenner met de map MR_Azure_Insights.

    2. Klik op Map selecterenterwijl de map MR_Azure_Application_Insights is geselecteerd. Het bouwen van het project duurt ongeveer een minuut.

  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 in solution platformx86, Lokale computer.

  3. Selecteer foutopsporing in de oplossingsconfiguratie.

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

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

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

  6. Start de mixed reality-toepassing.

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

Belangrijk

Hoewel de gemiddelde wachttijd voor het verzamelen van gebeurtenissen en metrische gegevens door de service ongeveer 15 minuten duurt, kan dit in sommige gevallen maximaal 1 uur duren.

Hoofdstuk 14- De Application Insights Service-portal

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

  1. Terug naar uw Application Insights Service-portal.

  2. Selecteer Metrics Explorer.

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

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

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

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

    Schermopname van het zoekvenster met de resultaten van een aangepast gebeurtenisfilter.

Uw Application Insights Service-toepassing 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 van de cursus.

Bonusoefeningen

Oefening 1

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

Oefening 2

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