HoloLens (primera generación) y Azure 309: Application Insights

Nota

Los tutoriales de Mixed Reality Academy se han diseñado teniendo en cuenta HoloLens (1.ª generación) y los cascos envolventes de realidad mixta. Por lo tanto, creemos que es importante conservar estos tutoriales para los desarrolladores que sigan buscando instrucciones sobre el desarrollo para esos dispositivos. Estos tutoriales no se actualizarán con los conjuntos de herramientas o las interacciones más recientes que se usan para HoloLens 2. Se mantendrán para que sigan funcionando en los dispositivos compatibles. Habrá una nueva serie de tutoriales que se publicarán en el futuro que demostrarán cómo desarrollar para HoloLens 2. Este aviso se actualizará con un vínculo a esos tutoriales cuando se publiquen.

Pantalla de bienvenida del tutorial de Mixed Reality Academy.

En este curso, aprenderá a agregar funcionalidades de Application Insights a una aplicación de realidad mixta mediante la API de Aplicación de Azure Insights para recopilar análisis relacionados con el comportamiento del usuario.

Application Insights es un servicio de Microsoft, lo que permite a los desarrolladores recopilar análisis de sus aplicaciones y administrarlos desde un portal fácil de usar. El análisis puede ser cualquier cosa, desde el rendimiento hasta la información personalizada que le gustaría recopilar. Para más información, visite la página de Application Insights.

Después de completar este curso, tendrá una aplicación de casco envolvente de realidad mixta, que podrá hacer lo siguiente:

  1. Permita al usuario mirar y desplazarse por una escena.
  2. Desencadene el envío de análisis al servicio Application Insights mediante la mirada y la proximidad a objetos en escena.
  3. La aplicación también llamará al servicio, capturando información sobre qué objeto ha sido abordado más por el usuario, en las últimas 24 horas. Ese objeto cambiará su color a verde.

Este curso le enseñará a obtener los resultados del servicio Application Insights en una aplicación de ejemplo basada en Unity. Dependerá de usted aplicar estos conceptos a una aplicación personalizada que podría compilar.

Compatibilidad con dispositivos

Curso HoloLens Cascos envolventes
Realidad mixta y Azure (309): Application Insights ✔️ ✔️

Nota

Aunque este curso se centra principalmente en Windows Mixed Reality cascos envolventes (VR), también puede aplicar lo que aprende en este curso para Microsoft HoloLens. A medida que sigas con el curso, verás notas sobre los cambios que puedas necesitar para admitir HoloLens. Al usar HoloLens, es posible que observe algún eco durante la captura de voz.

Requisitos previos

Nota:

Este tutorial está diseñado para desarrolladores que tienen experiencia básica con Unity y C#. Tenga en cuenta también que los requisitos previos y las instrucciones escritas dentro de este documento representan lo que se ha probado y comprobado en el momento de la escritura (julio de 2018). Puede usar el software más reciente, como se muestra en el artículo sobre la instalación de las herramientas , aunque no debe asumirse que la información de este curso coincidirá perfectamente con lo que encontrará en el software más reciente que lo que se muestra a continuación.

Se recomienda el siguiente hardware y software para este curso:

Antes de empezar

Para evitar problemas al compilar este proyecto, se recomienda encarecidamente crear el proyecto en este tutorial en una carpeta raíz o casi raíz (las rutas de acceso de carpeta largas pueden causar problemas en tiempo de compilación).

Advertencia

Tenga en cuenta que los datos que van a Application Insights tardan tiempo, así que tenga paciencia. Si desea comprobar si el Servicio ha recibido sus datos, consulte el capítulo 14, que le mostrará cómo navegar por el portal.

Capítulo 1: Azure Portal

Para usar Application Insights, deberá crear y configurar un servicio de Application Insights en el Azure Portal.

  1. Inicie sesión en Azure Portal.

    Nota

    Si aún no tiene una cuenta de Azure, deberá crear una. Si sigue este tutorial en una situación de clase o laboratorio, pida a su instructor o a uno de los proctores que le ayuden a configurar la nueva cuenta.

  2. Una vez que haya iniciado sesión, haga clic en Nuevo en la esquina superior izquierda y busque Application Insights y haga clic en Entrar.

    Nota

    Es posible que la palabra New se haya reemplazado por Create a resource (Crear un recurso) en portales más recientes.

    Captura de pantalla que muestra Azure Portal, Insight está resaltado en el panel Todo.

  3. La nueva página a la derecha proporcionará una descripción del servicio Aplicación de Azure Insights. En la parte inferior izquierda de esta página, seleccione el botón Crear para crear una asociación con este servicio.

    Captura de pantalla de la pantalla application Insights, Crear está resaltada.

  4. Una vez que haya hecho clic en Crear:

    1. Inserte el nombre deseado para esta instancia de servicio.

    2. Como Tipo de aplicación, seleccione General.

    3. Seleccione una suscripción adecuada.

    4. Elija un grupo de recursos o cree uno nuevo. Un grupo de recursos proporciona una manera de supervisar, controlar el acceso, aprovisionar y administrar la facturación de una colección de recursos de Azure. Se recomienda mantener todos los servicios de Azure asociados a un único proyecto (por ejemplo, estos cursos) en un grupo de recursos común).

      Si desea obtener más información sobre los grupos de recursos de Azure, visite el artículo sobre el grupo de recursos.

    5. Seleccione una ubicación.

    6. También deberá confirmar que ha comprendido los términos y condiciones aplicados a este servicio.

    7. Seleccione Crear.

      Captura de pantalla de la ventana de Application Insights. El nombre y el tipo de aplicación están resaltados.

  5. Una vez que haya hecho clic en Crear, tendrá que esperar a que se cree el servicio, esto puede tardar un minuto.

  6. Una notificación aparecerá en el portal una vez creada la instancia de servicio.

    Captura de pantalla que muestra una parte de la cinta de menús, el icono de notificación está resaltado.

  7. Seleccione las notificaciones para explorar la nueva instancia de servicio.

    Captura de pantalla que muestra el cuadro de diálogo Implementación correcta, Ir al recurso está resaltado.

  8. Haga clic en el botón Ir al recurso en la notificación para explorar la nueva instancia de servicio. Se le lleva a la nueva instancia del servicio Application Insights .

    Captura de pantalla que muestra la instancia de Application Insights Service donde el nombre de la instancia es MyNewInsight.

    Nota

    Mantenga esta página web abierta y fácil de acceder, volverá aquí a menudo para ver los datos recopilados.

    Importante

    Para implementar Application Insights, deberá usar tres (3) valores específicos: clave de instrumentación, identificador de aplicación y clave de API. A continuación, verá cómo recuperar estos valores del servicio. Asegúrese de anotar estos valores en una página del Bloc de notas en blanco, ya que los usará pronto en el código.

  9. Para buscar la clave de instrumentación, deberá desplazarse hacia abajo en la lista de funciones de servicio y seleccionar Propiedades, la pestaña que se muestra mostrará la clave de servicio.

    Captura de pantalla que muestra las funciones de servicio, Las propiedades están resaltadas en la sección Configurar y la clave de instrumentación está resaltada en el panel principal.

  10. Un poco debajo de Propiedades, encontrará acceso a la API, que debe hacer clic. El panel de la derecha proporcionará el identificador de aplicación de la aplicación.

    Captura de pantalla en la que se muestran las funciones de servicio, se resalta A P I Access. La creación de una clave P I y la id. de aplicación se resaltan en el panel principal.

  11. Con el panel Id. de aplicación todavía abierto, haga clic en Crear clave de API, que abrirá el panel Crear clave de API .

    Captura de pantalla que muestra el panel de claves Create A P I (Crear una clave P I).

  12. En el panel Crear clave de API ahora, escriba una descripción y marque los tres cuadros.

  13. Haga clic en Generar clave. La clave de API se creará y mostrará.

    Captura de pantalla del panel Crear una clave P I que muestra la nueva información de clave de servicio.

    Advertencia

    Esta es la única vez que se mostrará la clave de servicio , por lo que asegúrese de realizar una copia de ella ahora.

Capítulo 2: Configuración del proyecto de Unity

A continuación se muestra una configuración típica para desarrollar con la realidad mixta y, como tal, es una buena plantilla para otros proyectos.

  1. Abra Unity y haga clic en Nuevo.

    Captura de pantalla de la ventana proyectos de Unity. No se muestra información del proyecto.

  2. Ahora deberá proporcionar un nombre de proyecto de Unity, insertar MR_Azure_Application_Insights. Asegúrese de que la plantilla está establecida en 3D. Establezca la ubicación en un lugar adecuado para usted (recuerde, más cerca de los directorios raíz es mejor). A continuación, haga clic en Crear proyecto.

    Captura de pantalla de la ventana nuevos proyectos de Unity, en la que se muestra la información del proyecto.

  3. Con Unity abierto, vale la pena comprobar que el Editor de scripts predeterminado está establecido en Visual Studio. Vaya a Editar > preferencias y, a continuación, en la nueva ventana, vaya a Herramientas externas. Cambie el Editor de scripts externos a Visual Studio 2017. Cierre la ventana Preferencias.

    Captura de pantalla que muestra que Visual Studio está configurado como editor de scripts externos.

  4. A continuación, vaya a Configuración de > compilación de archivos y cambie la plataforma a Plataforma universal de Windows, haciendo clic en el botón Cambiar plataforma.

    Captura de pantalla de la ventana Configuración de compilación, en la que se muestra la lista de selección plataforma. Plataforma universal de Windows está seleccionado.

  5. Vaya a Configuración de compilación de archivos > y asegúrese de que:

    1. El dispositivo de destino se establece en Cualquier dispositivo.

      Para la Microsoft HoloLens, establezca Dispositivo de destino en HoloLens.

    2. El tipo de compilación se establece en D3D.

    3. El SDK se establece en Latest installed (Más reciente instalado)

    4. Build and Run (Compilación y ejecución ) está establecido en Local Machine (Máquina local).

    5. Guarde la escena y agréguela a la compilación.

      1. Para ello, seleccione Agregar escenas abiertas. Aparecerá una ventana de guardado.

        Captura de pantalla de la ventana Configuración de compilación, se selecciona Agregar escenas abiertas.

      2. Cree una nueva carpeta para esto y cualquier escena futura y, a continuación, haga clic en el botón Nueva carpeta para crear una nueva carpeta, asígnela el nombre Escenas.

        Captura de pantalla de la ventana Guardar escena, la carpeta Escenas está seleccionada.

      3. Abra la carpeta Escenas recién creada y, a continuación, en el campo Nombre de archivo : texto, escriba ApplicationInsightsScene y, a continuación, haga clic en Guardar.

        Captura de pantalla de la ventana Guardar escena con el nombre de archivo especificado.

  6. La configuración restante, en Configuración de compilación, debe dejarse como predeterminada por ahora.

  7. En la ventana Configuración de compilación , seleccione Configuración del reproductor; se abrirá el panel relacionado en el espacio donde se encuentra el Inspector .

    Captura de pantalla de la pestaña Inspector en la que se muestra la configuración del reproductor.

  8. En este panel, es necesario comprobar algunas opciones de configuración:

    1. En la pestaña Otras configuraciones :

      1. La versión del entorno de ejecución de scripting debe ser Experimental (equivalente a .NET 4.6), que desencadenará la necesidad de reiniciar el editor.

      2. El back-end de scripting debe ser .NET

      3. El nivel de compatibilidad de API debe ser .NET 4.6

      Captura de pantalla de la pestaña Inspector que muestra los detalles en la sección de configuración de Otras opciones.

    2. En la pestaña Configuración de publicación, en Funcionalidades, active:

      • InternetClient

        Captura de pantalla de la lista Funcionalidades, se comprueba el cliente de Internet.

    3. Más abajo en el panel, en Configuración de XR (que se encuentra a continuación de Configuración de publicación), marque Virtual Reality Supported (Compatible con Virtual Reality), asegúrese de que se agrega el SDK de Windows Mixed Reality.

      Captura de pantalla de la sección X R Settings (Configuración de X R), se comprueba Virtual Reality Supported (Compatible con Realidad virtual).

  9. De nuevo en Configuración de compilación, los proyectos de C# de Unity ya no están atenuados; marque la casilla situada junto a esto.

  10. Cierre la ventana Build Settings (Configuración de compilación).

  11. Guarde la escena y el proyecto (ARCHIVO>SAVE SCENE /FILE>SAVE PROJECT).

Capítulo 3: Importación del paquete de Unity

Importante

Si desea omitir los componentes de configuración de Unity de este curso y continuar directamente en el código, no dude en descargar este paquete de Azure-MR-309.unitypackage, impórtelo en el proyecto como paquete personalizado. Esto también contendrá los archivos DLL del siguiente capítulo. Después de la importación, continúe desde el capítulo 6.

Importante

Para usar Application Insights en Unity, debe importar el archivo DLL para él, junto con el archivo DLL newtonsoft. Actualmente hay un problema conocido en Unity que requiere que se vuelvan a configurar los complementos después de la importación. Estos pasos (4 - 7 en esta sección) ya no serán necesarios después de que se haya resuelto el error.

Para importar Application Insights en su propio proyecto, asegúrese de que ha descargado ".unitypackage", que contiene los complementos. A continuación, haga lo siguiente:

  1. Agregue el archivo.unitypackage** a Unity mediante la opción de menú Importar > paquete > personalizado de activos.

  2. En el cuadro Importar paquete de Unity que aparece, asegúrese de que está seleccionado todo en Complementos (e incluidos).

    Captura de pantalla del cuadro de diálogo Importar paquete de Unity que muestra todos los elementos activados.

  3. Haga clic en el botón Importar para agregar los elementos al proyecto.

  4. Vaya a la carpeta Insights en Complementos en la vista Proyecto y seleccione solo los siguientes complementos:

    • Microsoft.ApplicationInsights

    Captura de pantalla del panel Proyecto, la carpeta Insights está abierta.

  5. Con este complemento seleccionado, asegúrese de que Cualquier plataforma está desactivada y, a continuación, asegúrese de que WSAPlayer también está desactivada y, a continuación, haga clic en Aplicar. Esto es solo para confirmar que los archivos están configurados correctamente.

    Captura de pantalla del panel Inspector en la que se muestra el Editor y el independiente activados.

    Nota

    Marcar los complementos como este, los configura para que solo se usen en el Editor de Unity. Hay un conjunto diferente de archivos DLL en la carpeta WSA que se usará después de exportar el proyecto desde Unity.

  6. A continuación, debe abrir la carpeta WSA , dentro de la carpeta Insights . Verá una copia del mismo archivo que configuró. Seleccione este archivo y, a continuación, en el inspector, asegúrese de que Cualquier plataforma está desactivada y, a continuación, asegúrese de que soloWSAPlayer esté activado. Haga clic en Aplicar.

    Captura de pantalla del panel Inspector que muestra W S A Player activado.

  7. Ahora deberá seguir los pasos 4 a 6, pero para los complementos newtonsoft en su lugar. Consulte la captura de pantalla siguiente para ver el aspecto que debe tener el resultado.

    Captura de pantalla de cuatro vistas de los paneles Proyecto e Inspector que muestran los resultados de la configuración de las selecciones de complementos y carpetas newtonsoft.

Capítulo 4: Configuración de los controles de usuario y cámara

En este capítulo, configurará la cámara y los controles para permitir que el usuario vea y se mueva en la escena.

  1. Haga clic con el botón derecho en un área vacía en el Panel de jerarquía y, a continuación, en Crear>vacío.

    Captura de pantalla del panel Hierarchy (Jerarquía), Create Empty (Crear vacío) está seleccionado.

  2. Cambie el nombre del nuevo GameObject vacío a Elemento primario de la cámara.

    Captura de pantalla del panel Jerarquía con cámara primaria seleccionada. Panel Inspector

  3. Haga clic con el botón derecho en un área vacía en el Panel de jerarquía y, a continuación, en El objeto 3D y, a continuación, en Sphere.

  4. Cambie el nombre de la esfera a mano derecha.

  5. Establezca la escala de transformación de la mano derecha en 0.1, 0.1, 0.1

    Captura de pantalla de los paneles Jerarquía e Inspector, la sección Transformar del panel Inspector está resaltada.

  6. Quite el componente Colisionador de esfera de la mano derecha haciendo clic en el engranaje del componente Colisionador de esferas y, a continuación, quitar componente.

    Captura de pantalla del panel Inspector, el icono de engranaje y Quitar componente están resaltados en la sección Colisionador de esferas.

  7. En el Panel de jerarquía, arrastre los objetos Cámara principal y Mano derecha al objeto Primario de la cámara .

    Captura de pantalla del panel Jerarquía con la cámara principal seleccionada, el panel Inspector muestra la cámara principal activada.

  8. Establezca la posición de transformación de la cámara principal y el objeto de mano derecha en 0, 0, 0.

    Captura de pantalla del panel Jerarquía con la cámara principal seleccionada, La configuración de transformación se resalta en el panel Inspector.

    Captura de pantalla del panel Jerarquía con la opción Mano derecha seleccionada, La configuración de transformación se resalta en el panel Inspector.

Capítulo 5: Configuración de los objetos en la escena de Unity

Ahora creará algunas formas básicas para la escena, con las que el usuario puede interactuar.

  1. Haga clic con el botón derecho en un área vacía en el Panel de jerarquía y, a continuación, en Objeto 3D y, después, seleccione Plano.

  2. Establezca la posición de transformación del plano en 0, -1, 0.

  3. Establezca la escala de transformación del plano en 5, 1, 5.

    Captura de pantalla de los paneles Escena, Jerarquía e Inspector. La sección Transformar del panel Inspector está resaltada.

  4. Cree un material básico para usarlo con el objeto Plane , de modo que las otras formas sean más fáciles de ver. Vaya al Panel del proyecto, haga clic con el botón derecho y, a continuación, crear, seguido de Carpeta, para crear una carpeta. Asígnelo el nombre Materiales.

    Captura de pantalla del panel Proyecto que muestra crear y carpeta resaltada.Captura de pantalla del panel Proyecto. Los materiales se resaltan en el panel Activos.

  5. Abra la carpeta Materiales y, a continuación, haga clic con el botón derecho, haga clic en Crear y, a continuación, en Material, para crear un nuevo material. Asígnelo azul.

    Captura de pantalla del panel Proyecto que muestra crear y material resaltado.Captura de pantalla del panel Proyecto. El azul está resaltado en el panel Materiales.

  6. Con el nuevo material azul seleccionado, mire el Inspector y haga clic en la ventana rectangular junto a Albedo. Seleccione un color azul (la siguiente imagen es Color hexadecimal: #3592FFFF). Haga clic en el botón Cerrar una vez que haya elegido.

    Captura de pantalla del panel Inspector. La sección de color está resaltada.

  7. Arrastre el nuevo material desde la carpeta Materiales hasta el plano recién creado, dentro de la escena (o colóquelo en el objeto Plane dentro de la jerarquía).

    Captura de pantalla del panel Escena que muestra el nuevo material de la carpeta Materiales.

  8. Haga clic con el botón derecho en un área vacía en el Panel de jerarquía y, a continuación , en objeto 3D, cápsula.

    • Con la cápsula seleccionada, cambie su posiciónde transformación a: -10, 1, 0.
  9. Haga clic con el botón derecho en un área vacía en el Panel jerarquía y, a continuación , en objeto 3D, cubo.

    • Con el cubo seleccionado, cambie su posiciónde transformación a: 0, 0, 10.
  10. Haga clic con el botón derecho en un área vacía en el Panel de jerarquía y, a continuación , en Objeto 3D, Esfera.

    • Con la esfera seleccionada, cambie su posiciónde transformación a: 10, 0, 0.

    Captura de pantalla de los paneles Escena, Jerarquía e Inspector. La cápsula está seleccionada en el panel Jerarquía.

    Nota

    Estos valores position son sugerencias. Puedes establecer las posiciones de los objetos en lo que quieras, aunque es más fácil para el usuario de la aplicación si los objetos no están demasiado lejos de la cámara.

  11. Cuando se ejecuta la aplicación, debe poder identificar los objetos dentro de la escena, para lograrlo, deben etiquetarse. Seleccione uno de los objetos y, en el panel Inspector , haga clic en Agregar etiqueta..., que intercambiará el Inspector con el panel Etiquetas & Capas .

    Captura de pantalla del panel Inspector que muestra la opción Agregar etiqueta resaltada.Captura de pantalla del panel Inspector que muestra etiquetas y capas resaltadas.

  12. Haga clic en el símbolo + (más) y escriba el nombre de etiqueta como ObjectInScene.

    Captura de pantalla del panel Inspector con etiquetas y capas seleccionadas. El cuadro de diálogo Nuevo nombre de etiqueta está resaltado.

    Advertencia

    Si usa un nombre diferente para la etiqueta, deberá asegurarse de que este cambio también se realiza en los scripts DataFromAnalytics, ObjectTrigger y Gaze, para que los objetos se encuentren y detecten, dentro de la escena.

  13. Con la etiqueta creada, ahora debe aplicarla a los tres objetos. En jerarquía, mantenga presionada la tecla Mayús y haga clic en los objetos Capsule, Cube y Sphere, y, a continuación, en inspector, haga clic en el menú desplegable junto a Tag y, a continuación, haga clic en la etiqueta ObjectInScene que ha creado.

    Captura de pantalla del panel Inspector, una flecha apunta a Etiqueta. El menú Sin etiqueta muestra la opción Sin etiquetar activada y ObjectInScene está seleccionada.Captura de pantalla que muestra dos menús con Crear y carpeta resaltados.

Capítulo 6: Creación de la clase ApplicationInsightsTracker

El primer script que necesita crear es ApplicationInsightsTracker, que es responsable de:

  1. Creación de eventos basados en interacciones de usuario que se van a enviar a Aplicación de Azure Insights.

  2. Crear nombres de eventos adecuados, en función de la interacción del usuario.

  3. Envío de eventos a la instancia del servicio Application Insights.

Para crear esta clase:

  1. Haga clic con el botón derecho en el Panel del proyecto y, a continuación, en Crear>carpeta. Asigne un nombre a la carpeta Scripts.

    Captura de pantalla del panel Proyectos. El icono de carpeta Scripts está resaltado en el panel Activos.Captura de pantalla en la que se muestran las opciones en las que se seleccionan las opciones Crear y Script de C#.

  2. Con la carpeta Scripts creada, haga doble clic en ella para abrirla. A continuación, en esa carpeta, haga clic con el botón derecho en Crear>script de C#. Asigne al script el nombre ApplicationInsightsTracker.

  3. Haga doble clic en el nuevo script ApplicationInsightsTracker para abrirlo con Visual Studio.

  4. Actualice los espacios de nombres de la parte superior del script para que sean los siguientes:

        using Microsoft.ApplicationInsights;
        using Microsoft.ApplicationInsights.DataContracts;
        using Microsoft.ApplicationInsights.Extensibility;
        using UnityEngine;
    
  5. Dentro de la clase, inserte las siguientes variables:

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

    Establezca los valores instrumentationKey, applicationId y API_Key correctamente, mediante las claves de servicio de Azure Portal, como se mencionó en el capítulo 1, paso 9 en adelante.

  6. A continuación, agregue los métodos Start() y Awake(), a los que se llamará cuando se inicialice la clase:

        /// <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. Agregue los métodos responsables de enviar los eventos y métricas registrados por la aplicación:

        /// <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. Asegúrese de guardar los cambios en Visual Studio antes de volver a Unity.

Capítulo 7: Creación del script de mirada

El siguiente script que se va a crear es el script De mirada . Este script es responsable de crear un Raycast que se proyectará hacia delante desde la cámara principal, para detectar qué objeto está examinando el usuario. En este caso, Raycast tendrá que identificar si el usuario está mirando un objeto con la etiqueta ObjectInScene y, a continuación, contar cuánto tiempo ve el usuario en ese objeto.

  1. Haga doble clic en la carpeta Scripts para abrirla.

  2. Haga clic con el botón derecho en la carpeta Scripts y haga clic en Crear>script de C#. Asigne al script el nombre Gaze.

  3. Haga doble clic en el script para abrirlo con Visual Studio.

  4. Reemplace el código existente por el siguiente:

        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. Ahora es necesario agregar código para los métodos Awake() y Start().

        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. Dentro de la clase Gaze , agregue el código siguiente en el método Update() para proyectar un Raycast y detectar la acierto de destino:

        /// <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. Agregue el método ResetFocusedObject() para enviar datos a Application Insights cuando el usuario haya examinado un objeto.

        /// <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. Ya ha completado el script de mirada . Guarde los cambios en Visual Studio antes de volver a Unity.

Capítulo 8: Creación de la clase ObjectTrigger

El siguiente script que debe crear es ObjectTrigger, que es responsable de:

  • Agregar componentes necesarios para colisión a la cámara principal.
  • Detecta si la cámara está cerca de un objeto etiquetado como ObjectInScene.

Para crear el script:

  1. Haga doble clic en la carpeta Scripts para abrirla.

  2. Haga clic con el botón derecho en la carpeta Scripts y haga clic en Crear>script de C#. Asigne al script el nombre ObjectTrigger.

  3. Haga doble clic en el script para abrirlo con Visual Studio. Reemplace el código existente por el siguiente:

        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. Asegúrese de guardar los cambios en Visual Studio antes de volver a Unity.

Capítulo 9: Creación de la clase DataFromAnalytics

Ahora tendrá que crear el script DataFromAnalytics , que es responsable de:

  • Capturar datos de análisis sobre qué objeto ha sido abordado más por la cámara.
  • Con las claves de servicio, que permiten la comunicación con la instancia de Aplicación de Azure Insights Service.
  • Ordenar los objetos de la escena, según cuál tenga el recuento de eventos más alto.
  • Cambiar el color del material, del objeto más abordado, a verde.

Para crear el script:

  1. Haga doble clic en la carpeta Scripts para abrirla.

  2. Haga clic con el botón derecho en la carpeta Scripts y haga clic en Crear>script de C#. Asigne al script el nombre DataFromAnalytics.

  3. Haga doble clic en el script para abrirlo con Visual Studio.

  4. Inserte los siguientes espacios de nombres:

        using Newtonsoft.Json;
        using System;
        using System.Collections;
        using System.Collections.Generic;
        using System.Linq;
        using UnityEngine;
        using UnityEngine.Networking;
    
  5. Dentro del script, inserte lo siguiente:

        /// <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. Dentro de la clase DataFromAnalytics , justo después del método Start(), agregue el método siguiente llamado FetchAnalytics(). Este método es responsable de rellenar la lista de pares clave-valor, con un GameObject y un número de recuento de eventos de marcador de posición. A continuación, inicializa la corrutina GetWebRequest(). La estructura de consulta de la llamada a Application Insights también se puede encontrar en este método, como punto de conexión de la dirección URL de consulta .

        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. Justo debajo del método FetchAnalytics(), agregue un método llamado GetWebRequest(), que devuelve un IEnumerator. Este método es responsable de solicitar el número de veces que se ha llamado a un evento, correspondiente a un gameObject específico, en Application Insights. Cuando se han devuelto todas las consultas enviadas, se llama al método 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. El siguiente método es DetermineWinner(), que ordena la lista de pares GameObject e Int , según el recuento de eventos más alto. A continuación, cambia el color material de ese GameObject a verde (como comentarios para que tenga el recuento más alto). Esto muestra un mensaje con los resultados de análisis.

        /// <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. Agregue la estructura de clases que se usará para deserializar el objeto JSON, recibido de Application Insights. Agregue estas clases en la parte inferior del archivo de clase DataFromAnalytics , fuera de la definición de clase.

        /// <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. Asegúrese de guardar los cambios en Visual Studio antes de volver a Unity.

Capítulo 10: Crear la clase Movimiento

El script de movimiento es el siguiente script que deberá crear. Es responsable de:

  • Mover la cámara principal según la dirección hacia la que la cámara está mirando.
  • Agregar todos los demás scripts a objetos de escena.

Para crear el script:

  1. Haga doble clic en la carpeta Scripts para abrirla.

  2. Haga clic con el botón derecho en la carpeta Scripts y haga clic en Crear>script de C#. Asigne al script el nombre Movimiento.

  3. Haga doble clic en el script para abrirlo con Visual Studio.

  4. Reemplace el código existente por el siguiente:

        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. Dentro de la clase Movement , debajo del método Update() vacío, inserte los métodos siguientes que permiten al usuario usar el controlador de mano para moverse en el espacio virtual:

        /// <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. Por último, agregue la llamada al método Update().

        // Update is called once per frame
        void Update()
        {
            UpdateControllerState();
        }
    
  7. Asegúrese de guardar los cambios en Visual Studio antes de volver a Unity.

Capítulo 11: Configuración de las referencias de scripts

En este capítulo, debe colocar el script de movimiento en el elemento primario de la cámara y establecer sus destinos de referencia. Después, ese script controlará la colocación de los demás scripts donde deben estar.

  1. En la carpeta Scripts del Panel de proyectos, arrastre el script Movimiento al objeto Primario de la cámara, que se encuentra en el Panel de jerarquía.

    Captura de pantalla de los paneles Proyecto y Jerarquía. El movimiento está resaltado.

  2. Haga clic en el elemento primario de la cámara. En el Panel de jerarquía, arrastre el objeto Right Hand desde el Panel de jerarquía hasta el destino de referencia, Controller, en el Panel inspector. Establezca User Speed (Velocidad del usuario ) en 5, como se muestra en la imagen siguiente.

    Captura de pantalla que muestra los paneles Jerarquía e Inspector. Una línea conecta la mano derecha en ambos paneles.

Capítulo 12: Compilación del proyecto de Unity

Todo lo necesario para la sección Unity de este proyecto ya se ha completado, por lo que es el momento de compilarlo desde Unity.

  1. Vaya a Configuración de compilación (Configuración de compilación dearchivos>).

  2. En la ventana Configuración de compilación , haga clic en Compilar.

    Captura de pantalla de la ventana Configuración de compilación en la que se muestran escenas en compilación.

  3. Aparecerá una ventana Explorador de archivos, que le pedirá una ubicación para la compilación. Cree una nueva carpeta (haciendo clic en Nueva carpeta en la esquina superior izquierda) y asígnela el nombre BUILDS.

    Captura de pantalla de Explorador de archivos en la que se muestra la carpeta Compilaciones resaltada.

    1. Abra la nueva carpeta BUILDS y cree otra carpeta (con Nueva carpeta una vez más) y asígnela el nombre MR_Azure_Application_Insights.

      Captura de pantalla del Explorador de archivos que muestra la carpeta MR_Azure_Insights.

    2. Con la carpeta MR_Azure_Application_Insights seleccionada, haga clic en Seleccionar carpeta. El proyecto tardará un minuto en compilarse.

  4. Después de Compilar, Explorador de archivos aparecerá en la que se muestra la ubicación del nuevo proyecto.

Capítulo 13: Implementación de MR_Azure_Application_Insights aplicación en la máquina

Para implementar la aplicación MR_Azure_Application_Insights en el equipo local:

  1. Abra el archivo de solución de la aplicación de MR_Azure_Application_Insights en Visual Studio.

  2. En la Plataforma de soluciones, seleccione x86, Máquina local.

  3. En Configuración de la solución , seleccione Depurar.

    Captura de pantalla de la pantalla Configuración de la solución de Visual Studio que muestra Depurar en la barra de menús.

  4. Vaya al menú Compilar y haga clic en Implementar solución para transferir localmente la aplicación a la máquina.

  5. La aplicación debería aparecer ahora en la lista de aplicaciones instaladas, lista para iniciarse.

  6. Inicie la aplicación de realidad mixta.

  7. Muévalo por la escena, acercándose a los objetos y buscándolos, cuando Azure Insight Service haya recopilado suficientes datos de eventos, establecerá el objeto al que se ha acercado más a verde.

Importante

Mientras que el tiempo medio de espera para que el servicio recopile los eventos y las métricas tarda aproximadamente 15 minutos, en algunas ocasiones puede tardar hasta 1 hora.

Capítulo 14: Portal del servicio Application Insights

Una vez que haya recorrido por la escena y visto varios objetos, puede ver los datos recopilados en el portal del servicio Application Insights .

  1. Volver al portal del servicio Application Insights.

  2. Seleccione Explorador de métricas.

    Captura de pantalla del panel MyNewInsight que muestra la lista de opciones. El Explorador de métricas aparece en la sección Investigar.

  3. Se abrirá en una pestaña que contiene el gráfico, que representa los eventos y las métricas relacionados con la aplicación. Como se mencionó anteriormente, los datos pueden tardar algún tiempo (hasta 1 hora) en mostrarse en el gráfico.

    Captura de pantalla del Explorador de métricas que muestra el gráfico de eventos y métricas.

  4. Seleccione la barra Eventos en total de eventos por versión de la aplicación para ver un desglose detallado de los eventos con sus nombres.

    Captura de pantalla del panel Buscar que muestra los resultados de un filtro de eventos personalizado.

La aplicación de Application Insights Service finalizada

Enhorabuena, ha creado una aplicación de realidad mixta que aprovecha el servicio Application Insights para supervisar la actividad del usuario dentro de la aplicación.

Pantalla de bienvenida del curso.

Ejercicios de bonificación

Ejercicio 1

Intente generar, en lugar de crear manualmente, los objetos ObjectInScene y establezca sus coordenadas en el plano dentro de los scripts. De este modo, podría preguntar a Azure cuál era el objeto más popular (ya sea desde los resultados de mirada o proximidad) y generar uno adicional de esos objetos.

Ejercicio 2

Ordene los resultados de Application Insights por tiempo, de modo que obtenga los datos más relevantes e implemente esa información confidencial en la aplicación.