Compartir a través de


HoloLens (1.ª generación) y Azure 309: Application Insights

Nota:

Los tutoriales de Mixed Reality Academy se diseñaron con HoloLens (1.ª generación) y Mixed Reality cascos inmersivos en mente. Por lo tanto, creemos que es importante dejar estos tutoriales en su lugar para los desarrolladores que siguen buscando orientación en 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 seguir trabajando 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 con respecto al comportamiento del usuario.

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

Una vez completado este curso, tendrá una aplicación de casco envolvente de realidad mixta, que podrá hacer lo siguiente:

  1. Permitir que el usuario mire y se mueva alrededor de una escena.
  2. Desencadene el envío de análisis al servicio Application Insights mediante Mirada y proximidad a objetos en la escena.
  3. La aplicación también llamará al servicio, capturando información sobre qué objeto se ha acercado más al 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 estar compilando.

Compatibilidad con dispositivos

Curso HoloLens Cascos envolventes
MR y Azure 309: Application Insights ✔️ ✔️

Nota:

Aunque este curso se centra principalmente en Windows Mixed Reality cascos envolventes (VR), también puedes aplicar lo que aprendes en este curso a Microsoft HoloLens. A medida que siga el curso, verá notas sobre los cambios que pueda 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 de este documento representan lo que se ha probado y comprobado en el momento de la escritura (julio de 2018). Usted es libre de usar el software más reciente, como se muestra en el artículo instalar las herramientas , aunque no se debe suponer que la información de este curso coincidirá perfectamente con lo que encontrará en el software más reciente de 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 sea paciente. 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 aula o laboratorio, pida ayuda a su instructor o a uno de los responsables para configurar la nueva cuenta.

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

    Nota:

    Es posible que la palabra Nuevo se haya reemplazado por Crear un recurso en portales más recientes.

    Captura de pantalla en la que se muestra Azure Portal, Insight se resalta en el panel Todo.

  3. La nueva página de 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 de Application Insights, La opción 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 del 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, lo que puede tardar un minuto.

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

    Captura de pantalla que muestra una parte de la cinta de opciones de menú, 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 de la notificación para explorar la nueva instancia de servicio. Se le llevará a la nueva instancia del servicio Application Insights .

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

    Nota:

    Mantenga esta página web abierta y de fácil acceso, volverá aquí con frecuencia 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 por la lista de funciones de servicio y seleccionar Propiedades; la pestaña mostrada mostrará la clave de servicio.

    Captura de pantalla que muestra las funciones de servicio, Propiedades se resalta en la sección Configurar y Clave de instrumentación se resalta en el panel principal.

  10. A continuación, propiedades, encontrará acceso de API, en el 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 el acceso A P I. En el panel principal se resaltan Crear una clave de I P y un identificador de aplicación.

  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 Crear una P I.

  12. En el panel Crear clave de API ahora abierto, escriba una descripción y marque las tres casillas.

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

    Captura de pantalla del panel de claves Crear una 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 tendrá que 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 algún lugar adecuado para usted (recuerde que es mejor estar más cerca de los directorios raíz). 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 script predeterminado Editor está establecido en Visual Studio. Vaya a Editar > preferencias y, a continuación, en la nueva ventana, vaya a Herramientas externas. Cambie Editor de script externo a Visual Studio 2017. Cierre la ventana Preferencias .

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

  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 de plataforma. Plataforma universal de Windows está seleccionada.

  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 el Microsoft HoloLens, establezca Dispositivo de destino en HoloLens.

    2. Tipo de compilación se establece en D3D

    3. El SDK está establecido en Latest installed (Instalación más reciente)

    4. Compilación y ejecución se establecen en Máquina local

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

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

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

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

        Captura de pantalla de la ventana Guardar escena, se selecciona la carpeta Escenas.

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

  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 que muestra la configuración del reproductor.

  8. En este panel, es necesario comprobar algunos valores:

    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), lo 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 en la que se muestran los detalles de la sección de configuración de Otras configuraciones.

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

      • InternetClient

        Captura de pantalla de la lista Funcionalidades, el cliente de Internet está activado.

    3. Más abajo en el panel, en Configuración de XR (que se encuentra debajo de Configuración de publicación), marque Realidad virtual compatible y 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), Virtual Reality Supported (Realidad virtual admitida) está activada.

  9. De nuevo en Configuración de compilación, Proyectos de C# de Unity ya no está atenuado; active la casilla situada junto a esta.

  10. Cierre la ventana Configuración de compilación.

  11. Guarde la escena y el proyecto (ARCHIVO>GUARDAR ESCENA /ARCHIVO>GUARDAR PROYECTO).

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, descargue este paquete Azure-MR-309.unity, impórtelo en el proyecto como un paquete personalizado. Esto también contendrá los archivos DLL del capítulo siguiente. 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 de Newtonsoft. Actualmente hay un problema conocido en Unity que requiere que los complementos se vuelvan a configurar después de la importación. Estos pasos (del 4 al 7 de 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 the.unitypackage** a Unity mediante la opción de menú Paquete > personalizado de importación de recursos>.

  2. En el cuadro Import Unity Package (Importar paquete de Unity ) que aparece, asegúrese de que todo en (e including) Plugins (Incluir) complementos esté seleccionado.

    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é desactivado 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 Editor e independiente activados.

    Nota:

    Al marcar los complementos de este modo, 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 en la que se muestra W S A Player activado.

  7. Ahora tendrá que seguir los pasos del 4 al 6, pero para los complementos de Newtonsoft en su lugar. Vea la captura de pantalla siguiente para ver el aspecto que debería tener el resultado.

    Captura de pantalla de cuatro vistas de los paneles Project e Inspector que muestran los resultados de la configuración de las selecciones de carpeta y complemento newtonsoft.

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

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 Jerarquía y, a continuación, en Crear>vacío.

    Captura de pantalla del panel Jerarquía, se selecciona Crear vacío.

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

    Captura de pantalla del panel Jerarquía con el elemento primario de la cámara seleccionado. Panel Inspector

  3. Haga clic con el botón derecho en un área vacía en el panel Jerarquía, luego en Objeto 3D y, a continuación, en Esfera.

  4. Cambie el nombre de la esfera a la 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 engranaje en el componente Colisionador de esfera y, a continuación, quitar componente.

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

  7. En el panel Jerarquía, arrastre los objetos Cámara principal y Mano derecha al objeto Principal 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 la 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 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 Jerarquía, luego en Objeto 3D y, a continuación, seleccione Plano.

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

  3. Establezca la escala de transformación de 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, haga clic en Crear, seguido de Carpeta, para crear una nueva carpeta. Asígnele el nombre Materiales.

    Captura de pantalla del panel Proyecto que muestra Crear y Carpeta resaltados. Captura de pantalla del panel Proyecto. Los materiales se resaltan en el panel Activos.

  5. Abra la carpeta Materiales , haga clic con el botón derecho, haga clic en Crear y, después, en Material, para crear un nuevo material. Asígnele el nombre Azul.

    Captura de pantalla del panel Proyecto en la que se muestra Crear y Material resaltados. Captura de pantalla del panel Proyecto. El color azul está resaltado en el panel Materiales.

  6. Con el nuevo material azul seleccionado, examine el Inspector y haga clic en la ventana rectangular junto a Albedo. Seleccione un color azul (la imagen siguiente 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 Plano 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 Jerarquía y, a continuación , en Objeto 3D, Cápsula.

    • Con la cápsula seleccionada, cambie su posición de 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ón de transformación a: 0, 0, 10.
  10. Haga clic con el botón derecho en un área vacía en el panel 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 de posición son sugerencias. Puede establecer las posiciones de los objetos en lo que desee, aunque es más fácil para el usuario de la aplicación si las distancias de los objetos no están demasiado lejos de la cámara.

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

    Captura de pantalla del panel Inspector en la que se muestra la opción Agregar etiqueta resaltada. Captura de pantalla del panel Inspector en la que se muestran etiquetas y capas resaltados.

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

    Captura de pantalla del panel Inspector con etiquetas y capas seleccionados. 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 realice en los scripts DataFromAnalytics, ObjectTrigger y Gaze, más adelante, 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, a continuación, haga clic en los objetos Capsule, Cube y Sphere, y, a continuación, en inspector, haga clic en el menú desplegable junto con Etiqueta 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 etiquetar muestra Untagged checked (Sin etiquetar) y ObjectInScene está seleccionado. 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 debe crear es ApplicationInsightsTracker, que es responsable de:

  1. Creación de eventos basados en interacciones del usuario para enviar a Aplicación de Azure Insights.

  2. Crear nombres de evento 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 luego en Crear>carpeta. Asigne a la carpeta el nombre Scripts.

    Captura de pantalla del panel Proyectos. El icono de carpeta Scripts está resaltado en el panel Recursos. Captura de pantalla que muestra las opciones de menú donde están seleccionadas 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 en 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 menciona 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 la clase se inicialice:

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

El siguiente script que se va a crear es el script Gaze . Este script es responsable de crear un Raycast que se proyectará hacia delante desde la cámara principal, para detectar qué objeto está mirando 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 mira el usuario a ese objeto.

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

  2. Haga clic con el botón derecho dentro de 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 lo 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 el 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 Gaze . 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 los componentes necesarios para la colisión a la cámara principal.
  • Detectar 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 abrirlo.

  2. Haga clic con el botón derecho dentro de 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 lo 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:

  • Captura de datos de análisis sobre qué objeto se ha acercado más a la cámara.
  • Con las claves de servicio, que permiten la comunicación con la instancia del servicio Aplicación de Azure Insights.
  • Ordenar los objetos de la escena, según el cual tiene el mayor recuento de eventos.
  • 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 abrirlo.

  2. Haga clic con el botón derecho dentro de 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. En el 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. En la clase DataFromAnalytics , justo después del método Start(), agregue el siguiente método denominado FetchAnalytics(). Este método es responsable de rellenar la lista de pares de valores clave, 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 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 denominado 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 devuelven 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 del 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 clase 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: Creación de la clase Movement

El script Movimiento es el siguiente script que tendrá que crear. Es responsable de:

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

Para crear el script:

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

  2. Haga clic con el botón derecho dentro de 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 lo 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. En 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 dentro del 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, deberá colocar el script Movimiento en el elemento primario de la cámara y establecer sus destinos de referencia. A continuación, ese script controlará la colocación de los demás scripts donde necesiten estar.

  1. En la carpeta Scripts del Panel de proyectos, arrastre el script Movimiento al objeto Primario de la cámara, ubicado 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 la 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

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

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

  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 la 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ígnele el nombre BUILDS.

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

    1. Abra la nueva carpeta BUILDS y cree otra carpeta (con Nueva carpeta una vez más) y asígnele 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 más o menos en compilarse.

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

Capítulo 13: Implementación de MR_Azure_Application_Insights aplicación en el equipo

Para implementar la aplicación MR_Azure_Application_Insights en la máquina local:

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

  2. En 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, listas para iniciarse.

  6. Inicie la aplicación de realidad mixta.

  7. Moverse por la escena, acercarse a los objetos y mirarlos, cuando Azure Insight Service haya recopilado suficientes datos de eventos, establecerá el objeto que más se haya acercado a verde.

Importante

Aunque el tiempo medio de espera para que el servicio recopile los eventos y métricas tarda unos 15 minutos, en algunas ocasiones puede tardar hasta una hora.

Capítulo 14: Portal del servicio Application Insights

Una vez que haya recorrido la escena y haya mirado 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 en la que se 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 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 Eventosen Total de eventos por versión de aplicación para ver un desglose detallado de los eventos con sus nombres.

    Captura de pantalla del panel Búsqueda que muestra los resultados de un filtro de eventos personalizado.

Finalizó la aplicación del servicio Application Insights

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 por mirada o por resultados de 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 de tiempo en la aplicación.