HoloLens (prima generazione) e Azure 309: Application Insights

Nota

Le esercitazioni di Mixed Reality Academy sono state progettate in base a HoloLens (prima generazione) e ai visori VR immersive di realtà mista. Pertanto, riteniamo importante lasciarle a disposizione degli sviluppatori a cui serve ancora materiale sussidiario per lo sviluppo di questi dispositivi. Queste esercitazioni non verranno aggiornate con i set di strumenti o le interazioni più recenti usati per HoloLens 2. Rimarranno invariate per consentire di continuare a lavorare sui dispositivi supportati. Ci sarà una nuova serie di esercitazioni che verranno pubblicate in futuro che dimostreranno come sviluppare per HoloLens 2. Questo avviso verrà aggiornato con un collegamento a tali esercitazioni quando vengono pubblicate.

Schermata iniziale dell'esercitazione di Realtà mista Academy.

In questo corso si apprenderà come aggiungere funzionalità di Application Insights a un'applicazione di realtà mista usando l'API di applicazione Azure Insights per raccogliere analisi relative al comportamento degli utenti.

Application Insights è un servizio Microsoft che consente agli sviluppatori di raccogliere analisi dalle applicazioni e gestirle da un portale facile da usare. L'analisi può essere qualsiasi cosa, dalle prestazioni alle informazioni personalizzate che si desidera raccogliere. Per altre informazioni, visitare la pagina di Application Insights.

Dopo aver completato questo corso, si avrà un'applicazione vr immersive realtà mista, che sarà in grado di eseguire le operazioni seguenti:

  1. Consente all'utente di guardare e spostarsi intorno a una scena.
  2. Attivare l'invio di analisi al servizio Application Insights usando sguardo fisso e prossimità agli oggetti nella scena.
  3. L'app chiamerà anche il servizio, recuperando le informazioni su quale oggetto è stato avvicinato al massimo dall'utente, nelle ultime 24 ore. L'oggetto cambierà il colore in verde.

Questo corso illustra come ottenere i risultati dal servizio Application Insights in un'applicazione di esempio basata su Unity. Sarà necessario applicare questi concetti a un'applicazione personalizzata che si potrebbe creare.

Supporto di dispositivi

Corso HoloLens Visori VR immersive
MR e Azure 309: Application Insights ✔️

Nota

Anche se questo corso è incentrato principalmente su Windows Mixed Reality visori VR immersive, è anche possibile applicare ciò che si impara in questo corso per Microsoft HoloLens. Mentre si segue insieme al corso, verranno visualizzate note su tutte le modifiche che potrebbe essere necessario usare per supportare HoloLens. Quando si usa HoloLens, è possibile notare un'eco durante l'acquisizione vocale.

Prerequisiti

Nota

Questa esercitazione è progettata per gli sviluppatori che hanno esperienza di base con Unity e C#. Tenere presente anche che i prerequisiti e le istruzioni scritte all'interno di questo documento rappresentano ciò che è stato testato e verificato al momento della stesura del documento (luglio 2018). Si è liberi di usare il software più recente, come elencato all'interno dell'articolo installare gli strumenti , anche se non dovrebbe essere considerato che le informazioni in questo corso corrisponderanno perfettamente a ciò che troverete nel software più recente rispetto a quello elencato di seguito.

Per questo corso è consigliabile usare l'hardware e il software seguenti:

Prima di iniziare

Per evitare problemi durante la compilazione di questo progetto, è consigliabile creare il progetto in questa esercitazione in una cartella radice o quasi radice (i percorsi di cartelle lunghe possono causare problemi in fase di compilazione).

Avviso

Tenere presente che i dati che passano ad Application Insights richiedono tempo, quindi essere pazienti. Per verificare se il servizio ha ricevuto i dati, consultare il capitolo 14, che mostrerà come esplorare il portale.

Capitolo 1 - Portale di Azure

Per usare Application Insights, è necessario creare e configurare un servizio Application Insights nel portale di Azure.

  1. Accedi al portale di Azure.

    Nota

    Se non si ha già un account Azure, è necessario crearne uno. Se si segue questa esercitazione in una classe o in una situazione di laboratorio, chiedere all'insegnante o a uno dei proctor di assistenza per configurare il nuovo account.

  2. Dopo aver eseguito l'accesso, fare clic su Nuovo nell'angolo in alto a sinistra e cercare Application Insights e fare clic su Invio.

    Nota

    La parola Nuovo potrebbe essere stata sostituita con Crea una risorsa, nei portali più recenti.

    Screenshot che mostra il portale di Azure, informazioni dettagliate è evidenziato nel riquadro Tutto.

  3. La nuova pagina a destra fornirà una descrizione del servizio applicazione Azure Insights. Nella parte inferiore sinistra di questa pagina selezionare il pulsante Crea per creare un'associazione con questo servizio.

    Screenshot della schermata di Application Insights con l'opzione Crea evidenziata.

  4. Dopo aver fatto clic su Crea:

    1. Inserire il nome desiderato per questa istanza del servizio.

    2. In Tipo di applicazione selezionare Generale.

    3. Selezionare una sottoscrizione appropriata.

    4. Scegliere un gruppo di risorse o crearne uno nuovo. Un gruppo di risorse consente di monitorare, controllare l'accesso, effettuare il provisioning e gestire la fatturazione per una raccolta di asset di Azure. È consigliabile mantenere tutti i servizi di Azure associati a un singolo progetto (ad esempio, ad esempio questi corsi) in un gruppo di risorse comune.

      Per altre informazioni sui gruppi di risorse di Azure, vedere l'articolo sul gruppo di risorse.

    5. Selezionare un percorso.

    6. È anche necessario verificare di aver compreso i termini e le condizioni applicati al servizio.

    7. Selezionare Crea.

      Screenshot della finestra di Application Insights. Il nome e il tipo di applicazione sono evidenziati.

  5. Dopo aver fatto clic su Crea, è necessario attendere che il servizio venga creato, l'operazione potrebbe richiedere un minuto.

  6. Una notifica verrà visualizzata nel portale dopo la creazione dell'istanza del servizio.

    Screenshot che mostra una parte della barra multifunzione del menu, l'icona di notifica è evidenziata.

  7. Selezionare le notifiche per esplorare la nuova istanza del servizio.

    Screenshot che mostra la finestra di dialogo Distribuzione riuscita, Vai alla risorsa è evidenziata.

  8. Fare clic sul pulsante Vai alla risorsa nella notifica per esplorare la nuova istanza del servizio. Verrà visualizzata la nuova istanza del servizio Application Insights .

    Screenshot che mostra l'istanza del servizio Application Insights in cui il nome dell'istanza è MyNewInsight.

    Nota

    Mantenere aperta e facile l'accesso a questa pagina Web, si tornerà qui spesso per visualizzare i dati raccolti.

    Importante

    Per implementare Application Insights, è necessario usare tre (3) valori specifici: Chiave di strumentazione, ID applicazione e Chiave API. Di seguito viene illustrato come recuperare questi valori dal servizio. Assicurarsi di prendere nota di questi valori in una pagina vuota del Blocco note , perché verranno usati a breve nel codice.

  9. Per trovare la chiave di strumentazione, è necessario scorrere verso il basso l'elenco delle funzioni del servizio e selezionare Proprietà, la scheda visualizzata visualizzerà la chiave del servizio.

    Screenshot che mostra le funzioni del servizio, le proprietà sono evidenziate nella sezione Configura e la chiave di strumentazione è evidenziata nel riquadro principale.

  10. Sotto Proprietà è possibile trovare Accesso API, che è necessario fare clic. Il pannello a destra fornirà l'ID applicazione dell'app.

    Screenshot che mostra le funzioni del servizio, l'opzione A P I Access è evidenziata. Creare una chiave P I e un'applicazione I D sono evidenziate nel riquadro principale.

  11. Con il pannello ID applicazione ancora aperto, fare clic su Crea chiave API, che aprirà il pannello Crea chiave API .

    Screenshot che mostra il pannello dei tasti Create A P I .

  12. All'interno del pannello Crea chiave API digitare una descrizione e selezionare le tre caselle.

  13. Fare clic su Genera chiave. La chiave API verrà creata e visualizzata.

    Screenshot del pannello Crea chiave P I che mostra le nuove informazioni sulla chiave del servizio.

    Avviso

    Questa è l'unica volta che verrà visualizzata la chiave del servizio , quindi assicurarsi di crearne una copia.

Capitolo 2 - Configurare il progetto Unity

Di seguito è riportata una configurazione tipica per lo sviluppo con la realtà mista e, di conseguenza, è un modello valido per altri progetti.

  1. Aprire Unity e fare clic su Nuovo.

    Screenshot della finestra Progetti Unity. Non vengono visualizzate informazioni sul progetto.

  2. A questo punto è necessario specificare un nome di progetto Unity, inserire MR_Azure_Application_Insights. Assicurarsi che il modello sia impostato su 3D. Impostare La posizione su un punto appropriato per l'utente (tenere presente che più vicino alle directory radice è preferibile). Fare quindi clic su Crea progetto.

    Screenshot della finestra Nuovi progetti unity che mostra le informazioni sul progetto.

  3. Con Unity aperto, vale la pena verificare che l'editor di script predefinito sia impostato su Visual Studio. Passare a Modifica > preferenze e quindi dalla nuova finestra passare a Strumenti esterni. Modificare l'editor di script esterni in Visual Studio 2017. Chiudere la finestra Preferenze .

    Screenshot che mostra che Visual Studio è configurato come editor di script esterno.

  4. Passare quindi a Impostazioni compilazione file > e impostare la piattaforma su piattaforma UWP (Universal Windows Platform) facendo clic sul pulsante Cambia piattaforma.

    Screenshot della finestra Build Settings (Impostazioni compilazione) che mostra l'elenco di selezione Piattaforma. piattaforma UWP (Universal Windows Platform) selezionato.

  5. Passare a Impostazioni di compilazione file > e assicurarsi che:

    1. Il dispositivo di destinazione è impostato su Qualsiasi dispositivo

      Per il Microsoft HoloLens, impostare Dispositivo di destinazione su HoloLens.

    2. Il tipo di compilazione è impostato su D3D

    3. L'SDK è impostato su Più recente installato

    4. Compilazione ed esecuzione è impostata su Computer locale

    5. Salvare la scena e aggiungerla alla compilazione.

      1. A tale scopo, selezionare Aggiungi scene aperte. Verrà visualizzata una finestra di salvataggio.

        Screenshot della finestra Impostazioni di compilazione, è selezionata l'opzione Aggiungi scene aperte.

      2. Creare una nuova cartella e qualsiasi scena futura, quindi fare clic sul pulsante Nuova cartella per creare una nuova cartella, denominarla Scene.

        Screenshot della finestra Salva scena, viene selezionata la cartella Scene.

      3. Aprire la cartella Scenes appena creata e quindi nel campo Nome file: digitare ApplicationInsightsScene, quindi fare clic su Salva.

        Screenshot della finestra Salva scena con il nome file immesso.

  6. Le impostazioni rimanenti, in Impostazioni di compilazione, devono essere lasciate come predefinite per il momento.

  7. Nella finestra Build Settings (Impostazioni compilazione) selezionare Player Settings (Impostazioni lettore), verrà aperto il pannello correlato nello spazio in cui si trova il controllo .

    Screenshot della scheda Inspector (Controllo) che mostra Le impostazioni del lettore.

  8. In questo pannello è necessario verificare alcune impostazioni:

    1. Nella scheda Altre impostazioni :

      1. La versione del runtime di scripting deve essere sperimentale (equivalente a .NET 4.6), che attiverà la necessità di riavviare l'editor.

      2. Il back-end di scripting deve essere .NET

      3. Il livello di compatibilità dell'API deve essere .NET 4.6

      Screenshot della scheda Inspector (Controllo) che mostra i dettagli nella sezione di configurazione di Other Settings (Altre impostazioni).

    2. Nella scheda Impostazioni di pubblicazione , in Funzionalità, selezionare:

      • InternetClient

        Screenshot dell'elenco Funzionalità, il client Internet è selezionato.

    3. Più in basso nel pannello, in Impostazioni XR (disponibile sotto Impostazioni di pubblicazione), selezionare Virtual Reality Supported (Realtà virtuale supportata), assicurarsi che sia stato aggiunto Windows Mixed Reality SDK.

      Screenshot della sezione X R Settings (Impostazioni X R), virtual reality supported (Realtà virtuale supportata) selezionata.

  9. Tornare alle impostazioni di compilazione, i progetti C# unity non sono più disattivati; selezionare la casella di controllo accanto a questa.

  10. Chiudere la finestra Build Settings (Impostazioni di compilazione).

  11. Salvare la scena e il progetto (FILE>SAVE SCENE /FILE>SAVE PROJECT).

Capitolo 3 - Importare il pacchetto Unity

Importante

Se si vuole ignorare i componenti di Configurazione di Unity di questo corso e continuare direttamente nel codice, è possibile scaricare questo pacchetto Azure-MR-309.unitypackage, importarlo nel progetto come pacchetto personalizzato. Questo conterrà anche le DLL del capitolo successivo. Dopo l'importazione, continuare dal capitolo 6.

Importante

Per usare Application Insights all'interno di Unity, è necessario importare la DLL, insieme alla DLL Newtonsoft. Attualmente esiste un problema noto in Unity che richiede la riconfigurazione dei plug-in dopo l'importazione. Questi passaggi (da 4 a 7 in questa sezione) non saranno più necessari dopo la risoluzione del bug.

Per importare Application Insights nel proprio progetto, assicurarsi di aver scaricato il file '.unitypackage', contenente i plug-in. Procedere quindi come segue:

  1. Aggiungere the.unitypackage** a Unity usando l'opzione di menu Asset > Importa pacchetto > personalizzato pacchetto .

  2. Nella casella Import Unity Package (Importa pacchetto Unity ) visualizzata verificare che sia selezionata l'opzione Plug-in (e inclusi) in .

    Screenshot della finestra di dialogo Importa pacchetto Unity che mostra tutti gli elementi selezionati.

  3. Fare clic sul pulsante Importa per aggiungere gli elementi al progetto.

  4. Passare alla cartella Insights in Plugins (Plug-in ) nella visualizzazione Progetto e selezionare solo i plug-in seguenti:

    • Microsoft.ApplicationInsights

    Screenshot del pannello Progetto, la cartella Insights è aperta.

  5. Con questo plug-in selezionato, assicurarsi che Any Platform sia deselezionato, quindi assicurarsi che WSAPlayer sia deselezionato, quindi fare clic su Applica. In questo modo è sufficiente verificare che i file siano configurati correttamente.

    Screenshot del pannello Inspector (Controllo) che mostra l'editor e la versione autonoma selezionata.

    Nota

    Contrassegnando i plug-in come questo, li configura in modo che vengano usati solo nell'editor di Unity. Nella cartella WSA è presente un set diverso di DLL che verranno usate dopo l'esportazione del progetto da Unity.

  6. Successivamente, è necessario aprire la cartella WSA all'interno della cartella Insights . Verrà visualizzata una copia dello stesso file configurato. Selezionare questo file e quindi nel controllo verificare che Any Platform sia deselezionato, quindi assicurarsi che sia selezionatosoloWSAPlayer. Fare clic su Applica.

    Screenshot del pannello Inspector (Controllo) che mostra W S A Player selezionato.

  7. È ora necessario seguire i passaggi da 4 a 6, ma per i plug-in Newtonsoft . Vedere lo screenshot seguente per l'aspetto del risultato.

    Screenshot di quattro visualizzazioni dei pannelli Project and Inspector che mostrano i risultati della configurazione della cartella Newtonsoft e delle selezioni del plug-in.

Capitolo 4 - Configurare la fotocamera e i controlli utente

In questo capitolo si configureranno la fotocamera e i controlli per consentire all'utente di visualizzare e spostarsi nella scena.

  1. Fare clic con il pulsante destro del mouse in un'area vuota nel pannello Gerarchia, quindi scegliere Crea>vuoto.

    Screenshot del pannello Hierarchy (Gerarchia) e l'opzione Create Empty (Crea vuoto) è selezionata.

  2. Rinominare il nuovo GameObject vuoto in Camera Parent.

    Screenshot del pannello Hierarchy (Gerarchia) con l'opzione Camera Parent selezionata. Pannello Inspector

  3. Fare clic con il pulsante destro del mouse in un'area vuota nel pannello Gerarchia, quindi su Oggetto 3D, quindi su Sphere.

  4. Rinominare Sphere in Mano destra.

  5. Impostare la scala di trasformazione della mano destra su 0.1, 0.1, 0.1

    Screenshot dei pannelli Hierarchy and Inspector (Gerarchia e controllo), la sezione Transform (Trasforma) nel pannello Inspector (Controllo) è evidenziata.

  6. Rimuovere il componente Collisore Sphere dalla mano destra facendo clic sull'ingranaggio nel componente Collider sphere e quindi su Rimuovi componente.

    Screenshot del pannello Inspector (Controllo), l'icona a forma di ingranaggio e Remove Component (Rimuovi componente) sono evidenziate nella sezione Collider Sphere.

  7. Nel pannello Hierarchy (Gerarchia) trascinare la fotocamera principale e gli oggetti Right Hand nell'oggetto Camera Parent .

    Screenshot del pannello Gerarchia con la fotocamera principale selezionata, il pannello Inspector (Controllo) mostra La fotocamera principale selezionata.

  8. Impostare la posizione di trasformazione sia della fotocamera principale che dell'oggetto Right Hand su 0, 0, 0.

    Screenshot del pannello Hierarchy (Gerarchia) con l'opzione Main Camera selezionata, Le impostazioni di trasformazione sono evidenziate nel pannello Inspector (Controllo).

    Screenshot del pannello Gerarchia con mano destra selezionata, le impostazioni di trasformazione vengono evidenziate nel pannello Controllo.

Capitolo 5 - Configurare gli oggetti nella scena Unity

A questo punto si creeranno alcune forme di base per la scena, con cui l'utente può interagire.

  1. Fare clic con il pulsante destro del mouse su un'area vuota nel pannello gerarchia, quindi su oggetto 3D, quindi selezionare Piano.

  2. Impostare la posizione di trasformazione del piano su 0, -1, 0.

  3. Impostare la scala di trasformazione del piano su 5, 1, 5.

    Screenshot dei pannelli Scena, Gerarchia e Controllo. La sezione Trasforma nel pannello Inspector è evidenziata.

  4. Creare un materiale di base da usare con l'oggetto Plane , in modo che le altre forme siano più facili da visualizzare. Passare al pannello di progetto, fare clic con il pulsante destro del mouse, quindi creare una nuova cartella, quindi crearne una nuova. Denominarlo Material.

    Screenshot del pannello Progetto che mostra Crea e cartella evidenziata.Screenshot del pannello Progetto. I materiali sono evidenziati nel riquadro Asset.

  5. Aprire la cartella Materiali , quindi fare clic con il pulsante destro del mouse, scegliere Crea, quindi Materiale per creare un nuovo materiale. Denominarlo Blu.

    Screenshot del pannello Progetto che mostra Crea e Materiale evidenziato.Screenshot del pannello Progetto. Il blu è evidenziato nel riquadro Materiali.

  6. Con il nuovo materiale Blu selezionato, esaminare Il controllo e fare clic sulla finestra rettangolare insieme a Albedo. Selezionare un colore blu (l'immagine seguente è Hex Color: #3592FFFF). Fare clic sul pulsante chiudi dopo aver scelto.

    Screenshot del pannello Controllo. La sezione colore è evidenziata.

  7. Trascinare il nuovo materiale dalla cartella Material , nel piano appena creato, all'interno della scena o rilasciarlo nell'oggetto Plane all'interno della gerarchia.

    Screenshot del pannello Scena che mostra il nuovo materiale dalla cartella Material.

  8. Fare clic con il pulsante destro del mouse su un'area vuota nel pannello gerarchia, quindi su oggetto 3D, capsule.

    • Con l'opzione Capsule selezionata, modifica la relativa posizionedi trasformazione su: -10, 1, 0.
  9. Fare clic con il pulsante destro del mouse su un'area vuota nel pannello gerarchia, quindi su oggetto 3D, Cubo.

    • Con l'opzione Cube selezionata, modificare la relativa posizionedi trasformazione su: 0, 0, 10.
  10. Fare clic con il pulsante destro del mouse su un'area vuota nel pannello gerarchia, quindi su oggetto 3D, Sphere.

    • Con l'opzione Sphere selezionata, modifica la relativa posizionedi trasformazione su: 10, 0, 0.

    Screenshot dei pannelli Scena, Gerarchia e Controllo. La capsula è selezionata nel pannello Gerarchia.

    Nota

    Questi valori Position sono suggerimenti. È possibile impostare le posizioni degli oggetti su qualsiasi cosa si desidera, anche se è più facile per l'utente dell'applicazione se le distanze degli oggetti non sono troppo lontane dalla fotocamera.

  11. Quando l'applicazione è in esecuzione, deve essere in grado di identificare gli oggetti all'interno della scena, per ottenere questo risultato, devono essere contrassegnati. Selezionare uno degli oggetti e nel pannello Controllo fare clic su Aggiungi tag..., che scambia il controllo con il pannello Tag & Layer.

    Screenshot del pannello Controllo che mostra l'opzione Aggiungi tag evidenziata.Screenshot del pannello Controllo che mostra tag e livelli evidenziati.

  12. Fare clic sul simbolo + (più) e quindi digitare il nome del tag come ObjectInScene.

    Screenshot del pannello Controllo con tag e livelli selezionati. La finestra di dialogo Nuovo nome tag è evidenziata.

    Avviso

    Se si usa un nome diverso per il tag, è necessario assicurarsi che questa modifica venga apportata anche agli script DataFromAnalytics, ObjectTrigger e Gaze, in modo che gli oggetti vengano trovati e rilevati all'interno della scena.

  13. Con il tag creato, è ora necessario applicarlo a tutti e tre gli oggetti. Nella gerarchia tenere premuto il tasto Maiusc, quindi fare clic sul tag Capsule, Cube e Sphere, quindi scegliere il menu a discesa accanto a Tag, quindi fare clic sul tag ObjectInScene creato.

    Screenshot del pannello Controllo, una freccia punta a Tag. Il menu Untagged indica che è selezionata l'opzione Untagged e ObjectInScene.Screenshot che mostra due menu con Crea e Cartella evidenziata.

Capitolo 6 - Creare la classe ApplicationInsightsTracker

Il primo script da creare è ApplicationInsightsTracker, responsabile:

  1. Creazione di eventi in base alle interazioni utente da inviare a applicazione Azure Insights.

  2. Creazione di nomi di eventi appropriati, a seconda dell'interazione dell'utente.

  3. Invio di eventi all'istanza del servizio Application Insights.

Per creare questa classe:

  1. Fare clic con il pulsante destro del mouse nel pannello del progetto, quindi creare>cartella. Assegnare un nome alla cartella Script.

    Screenshot del pannello Progetti. L'icona della cartella Script è evidenziata nel riquadro Asset.Screenshot che mostra le opzioni in cui sono selezionate le opzioni, Crea e Script C#.

  2. Con la cartella Script creata, fare doppio clic su di essa per aprire. Quindi, all'interno di tale cartella, fare clic con il pulsante destro del mouse su Crea>script C#. Assegnare un nome allo script ApplicationInsightsTracker.

  3. Fare doppio clic sul nuovo script ApplicationInsightsTracker per aprirlo con Visual Studio.

  4. Aggiornare gli spazi dei nomi nella parte superiore dello script come indicato di seguito:

        using Microsoft.ApplicationInsights;
        using Microsoft.ApplicationInsights.DataContracts;
        using Microsoft.ApplicationInsights.Extensibility;
        using UnityEngine;
    
  5. All'interno della classe inserire le variabili seguenti:

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

    Nota

    Impostare i valori di strumentazioneKey, applicationId e API_Key in modo appropriato, usando le chiavi di servizio dal portale di Azure, come indicato nel capitolo 1, passaggio 9 in avanti.

  6. Aggiungere quindi i metodi Start() e Awake(), che verranno chiamati quando la classe inizializza:

        /// <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. Aggiungere i metodi responsabili dell'invio degli eventi e delle metriche registrate dall'applicazione:

        /// <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. Assicurarsi di salvare le modifiche in Visual Studio prima di tornare a Unity.

Capitolo 7 - Creare lo script Di sguardo

Lo script successivo da creare è lo script Gaze . Questo script è responsabile della creazione di un Raycast che verrà proiettato avanti dalla fotocamera principale, per rilevare l'oggetto che l'utente sta esaminando. In questo caso, raycast dovrà identificare se l'utente sta esaminando un oggetto con il tag ObjectInScene e quindi contare quanto tempo l'utente guarda a tale oggetto.

  1. Fare doppio clic sulla cartella Script per aprirla.

  2. Fare clic con il pulsante destro del mouse all'interno della cartella Script , fare clic su Crea>script C#. Assegnare allo script lo sguardo.

  3. Fare doppio clic sullo script per aprirlo con Visual Studio.

  4. Sostituire il codice esistente con quello seguente:

        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. Il codice per i metodi Awake() e Start() deve ora essere aggiunto.

        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. All'interno della classe Gaze aggiungere il codice seguente nel metodo Update() per proiettare un Raycast e rilevare il colpo di destinazione:

        /// <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. Aggiungere il metodo ResetFocusedObject() per inviare dati a Application Insights quando l'utente ha esaminato un oggetto.

        /// <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. A questo punto è stato completato lo script Gaze . Salvare le modifiche in Visual Studio prima di tornare a Unity.

Capitolo 8 - Creare la classe ObjectTrigger

Lo script successivo che è necessario creare è ObjectTrigger, responsabile di:

  • Aggiunta di componenti necessari per la collisione con la fotocamera principale.
  • Rilevamento se la fotocamera è vicina a un oggetto contrassegnato come ObjectInScene.

Per creare lo script:

  1. Fare doppio clic sulla cartella Script per aprirla.

  2. Fare clic con il pulsante destro del mouse all'interno della cartella Script , fare clic su Crea>script C#. Assegnare un nome allo script ObjectTrigger.

  3. Fare doppio clic sullo script per aprirlo con Visual Studio. Sostituire il codice esistente con quello seguente:

        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. Assicurarsi di salvare le modifiche in Visual Studio prima di tornare a Unity.

Capitolo 9 - Creare la classe DataFromAnalytics

È ora necessario creare lo script DataFromAnalytics , responsabile di:

  • Recupero dei dati di analisi su quale oggetto è stato avvicinato dalla fotocamera la maggior parte.
  • Uso delle chiavi di servizio che consentono la comunicazione con l'istanza del servizio applicazione Azure Insights.
  • Ordinamento degli oggetti nella scena, in base al quale ha il numero di eventi più alto.
  • Modifica del colore del materiale, dell'oggetto più avvicinato, al verde.

Per creare lo script:

  1. Fare doppio clic sulla cartella Script per aprirla.

  2. Fare clic con il pulsante destro del mouse all'interno della cartella Script , fare clic su Crea>script C#. Assegnare al nome lo script DataFromAnalytics.

  3. Fare doppio clic sullo script per aprirlo con Visual Studio.

  4. Inserire gli spazi dei nomi seguenti:

        using Newtonsoft.Json;
        using System;
        using System.Collections;
        using System.Collections.Generic;
        using System.Linq;
        using UnityEngine;
        using UnityEngine.Networking;
    
  5. All'interno dello script inserire quanto segue:

        /// <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. All'interno della classe DataFromAnalytics , subito dopo il metodo Start(), aggiungere il metodo seguente denominato FetchAnalytics(). Questo metodo è responsabile della popolamento dell'elenco delle coppie di valori chiave, con un GameObject e un numero di conteggio eventi segnaposto. Inizializza quindi la coroutine GetWebRequest(). La struttura di query della chiamata a Application Insights è disponibile anche all'interno di questo metodo, come endpoint URL query .

        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. Sotto il metodo FetchAnalytics() aggiungere un metodo denominato GetWebRequest(), che restituisce un IEnumerator. Questo metodo è responsabile della richiesta del numero di volte in cui un evento, corrispondente a un GameObject specifico, è stato chiamato in Application Insights. Quando tutte le query inviate sono state restituite, viene chiamato il metodo DetermineWinner().

        /// <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. Il metodo successivo è DetermineWinner(), che ordina l'elenco di coppie GameObject e Int , in base al numero di eventi più alto. Cambia quindi il colore del materiale di GameObject in verde (come feedback per il numero più alto). Viene visualizzato un messaggio con i risultati dell'analisi.

        /// <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. Aggiungere la struttura della classe che verrà usata per deserializzare l'oggetto JSON, ricevuto da Application Insights. Aggiungere queste classi nella parte inferiore del file di classe DataFromAnalytics , all'esterno della definizione della classe.

        /// <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. Assicurarsi di salvare le modifiche in Visual Studio prima di tornare a Unity.

Capitolo 10 - Creare la classe Movimento

Lo script Di spostamento è lo script successivo che sarà necessario creare. È responsabile di:

  • Spostare la fotocamera principale in base alla direzione in cui la fotocamera sta cercando.
  • Aggiunta di tutti gli altri script agli oggetti scene.

Per creare lo script:

  1. Fare doppio clic sulla cartella Script per aprirla.

  2. Fare clic con il pulsante destro del mouse all'interno della cartella Script , fare clic su Crea>script C#. Assegnare un nome al movimento dello script.

  3. Fare doppio clic sullo script per aprirlo con Visual Studio.

  4. Sostituire il codice esistente con quello seguente:

        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. All'interno della classe Movement , sotto il metodo Update() vuoto, inserire i metodi seguenti che consentono all'utente di usare il controller di mano per spostarsi nello spazio virtuale:

        /// <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. Aggiungere infine la chiamata al metodo all'interno del metodo Update().

        // Update is called once per frame
        void Update()
        {
            UpdateControllerState();
        }
    
  7. Assicurarsi di salvare le modifiche in Visual Studio prima di tornare a Unity.

Capitolo 11 - Configurazione dei riferimenti agli script

In questo capitolo è necessario inserire lo script Movimento nell'elemento Padre della fotocamera e impostare le destinazioni di riferimento. Tale script gestirà quindi l'inserimento degli altri script in cui devono essere.

  1. Dalla cartella Script nel pannello di progetto trascinare lo script Movimento nell'oggetto Camera Parent , situato nel pannello gerarchia.

    Screenshot dei pannelli Progetto e Gerarchia. Lo spostamento è evidenziato.

  2. Fare clic su Padre fotocamera. Nel pannello gerarchia trascinare l'oggetto Mano destra dal pannello gerarchia alla destinazione di riferimento, controller, nel pannello di controllo. Impostare La velocità utente su 5, come illustrato nell'immagine seguente.

    Screenshot che mostra i pannelli Gerarchia e Controllo. Una linea si connette a destra su entrambi i pannelli.

Capitolo 12 - Compilare il progetto Unity

Tutto ciò che è necessario per la sezione Unity di questo progetto è stato completato, quindi è il momento di compilarlo da Unity.

  1. Passare a Impostazioni di compilazione(Impostazioni compilazionefile>).

  2. Nella finestra Impostazioni di compilazione fare clic su Compila.

    Screenshot della finestra Impostazioni di compilazione che mostra scene in compilazione.

  3. Verrà visualizzata una finestra Esplora file, che richiede una posizione per la compilazione. Creare una nuova cartella (facendo clic su Nuova cartella nell'angolo superiore sinistro) e denominarla BUILD.

    Screenshot di Esplora file che mostra la cartella Build evidenziata.

    1. Aprire la nuova cartella BUILD e creare un'altra cartella (usando nuova cartella una volta di più) e denominarla MR_Azure_Application_Insights.

      Screenshot di Esplora file che mostra la cartella MR_Azure_Insights.

    2. Con la MR_Azure_Application_Insights cartella selezionata, fare clic su Seleziona cartella. Il progetto richiederà un minuto o così per compilare.

  4. In compilazioneEsplora file verrà visualizzata la posizione del nuovo progetto.

Capitolo 13 - Distribuire l'app MR_Azure_Application_Insights nel computer

Per distribuire l'app MR_Azure_Application_Insights nel computer locale:

  1. Aprire il file di soluzione dell'app MR_Azure_Application_Insights in Visual Studio.

  2. Nella piattaforma della soluzione selezionare x86, Computer locale.

  3. Nella configurazione della soluzione selezionare Debug.

    Screenshot della schermata Configurazione della soluzione di Visual Studio che mostra Debug nella barra dei menu.

  4. Passare al menu Compila e fare clic su Distribuisci soluzione per caricare sideload dell'applicazione nel computer.

  5. L'app dovrebbe ora essere visualizzata nell'elenco delle app installate, pronto per essere avviato.

  6. Avviare l'applicazione di realtà mista.

  7. Spostarsi intorno alla scena, avvicinarsi agli oggetti e esaminarli, quando il servizio Informazioni dettagliate di Azure ha raccolto dati di evento sufficienti, verrà impostato l'oggetto che è stato avvicinato al più verde.

Importante

Mentre il tempo di attesa medio per gli eventi e le metriche da raccogliere dal servizio richiede circa 15 minuti, in alcune occasioni potrebbe richiedere fino a 1 ora.

Capitolo 14 - Portale del servizio Application Insights

Dopo aver eseguito il roaming intorno alla scena e guardando diversi oggetti, è possibile visualizzare i dati raccolti nel portale del servizio Application Insights .

  1. Indietro al portale del servizio Application Insights.

  2. Selezionare Esplora metriche.

    Screenshot del pannello MyNewInsight che mostra l'elenco delle opzioni. Esplora metriche è elencato nella sezione Ricerca.

  3. Verrà aperta in una scheda contenente il grafico, che rappresenta gli eventi e le metriche correlate all'applicazione. Come accennato in precedenza, potrebbe richiedere tempo (fino a 1 ora) per visualizzare i dati nel grafico

    Screenshot di Esplora metriche che mostra gli eventi e il grafico delle metriche.

  4. Selezionare la barra Eventi nella versione totale degli eventi in base alla versione dell'applicazione per visualizzare una suddivisione dettagliata degli eventi con i relativi nomi.

    Screenshot del pannello Ricerca che mostra i risultati di un filtro evento personalizzato.

L'applicazione del servizio Application Insights completata

Congratulazioni, è stata creata un'app di realtà mista che sfrutta il servizio Application Insights per monitorare l'attività dell'utente all'interno dell'app.

Schermata iniziale del corso.

Esercizi bonus

Esercizio 1

Provare a generare, anziché creare manualmente, gli oggetti ObjectInScene e impostare le coordinate sul piano all'interno degli script. In questo modo, è possibile chiedere ad Azure quale fosse l'oggetto più popolare (dai risultati di sguardo o prossimità) e generarne uno aggiuntivo .

Esercizio 2

Ordinare i risultati di Application Insights in base al tempo, in modo da ottenere i dati più rilevanti e implementare tali dati sensibili all'ora nell'applicazione.