Partilhar via


HoloLens (1.ª geração) e Azure 309: Perspetivas da aplicação

Nota

Os tutoriais da Academia de Realidade Mista foram projetados com HoloLens (1ª geração) e Headsets Imersivos de Realidade Mista em mente. Como tal, sentimos que é importante deixar estes tutoriais no lugar para desenvolvedores que ainda estão procurando orientação no desenvolvimento para esses dispositivos. Esses tutoriais não serão atualizados com os conjuntos de ferramentas ou interações mais recentes que estão sendo usados para o HoloLens 2. Eles serão mantidos para continuar trabalhando nos dispositivos suportados. Haverá uma nova série de tutoriais que serão publicados no futuro que demonstrarão como desenvolver para o HoloLens 2. Este aviso será atualizado com um link para esses tutoriais quando eles forem publicados.

A tela de boas-vindas tutorial da Mixed Reality Academy.

Neste curso, você aprenderá como adicionar recursos do Application Insights a um aplicativo de realidade mista, usando a API do Azure Application Insights para coletar análises sobre o comportamento do usuário.

O Application Insights é um serviço da Microsoft, permitindo que os desenvolvedores coletem análises de seus aplicativos e as gerenciem a partir de um portal fácil de usar. A análise pode ser qualquer coisa, desde desempenho até informações personalizadas que você gostaria de coletar. Para obter mais informações, visite a página Application Insights.

Tendo concluído este curso, você terá um aplicativo de fone de ouvido imersivo de realidade mista, que será capaz de fazer o seguinte:

  1. Permita que o usuário olhe e se mova em torno de uma cena.
  2. Acione o envio de análises para o Serviço do Application Insights, usando o Olhar e a Proximidade com objetos em cena.
  3. O aplicativo também acionará o Serviço, buscando informações sobre qual objeto foi mais abordado pelo usuário, nas últimas 24 horas. Esse objeto mudará sua cor para verde.

Este curso ensinará como obter os resultados do Serviço Application Insights em um aplicativo de exemplo baseado em Unity. Caberá a você aplicar esses conceitos a um aplicativo personalizado que você pode estar criando.

Suporte de dispositivos

Curso HoloLens Auriculares imersivos
MR e Azure 309: Insights de aplicativos ✔️ ✔️

Nota

Embora este curso se concentre principalmente em fones de ouvido imersivos (VR) do Windows Mixed Reality, você também pode aplicar o que aprendeu neste curso ao Microsoft HoloLens. À medida que você acompanha o curso, você verá anotações sobre quaisquer alterações que você possa precisar empregar para dar suporte ao HoloLens. Ao utilizar o HoloLens, poderá notar algum eco durante a captura de voz.

Pré-requisitos

Nota

Este tutorial foi projetado para desenvolvedores que têm experiência básica com Unity e C#. Tenha também em atenção que os pré-requisitos e as instruções escritas contidas neste documento representam o que foi testado e verificado no momento da redação (julho de 2018). Você é livre para usar o software mais recente, conforme listado no artigo instalar as ferramentas , embora não se deva presumir que as informações neste curso corresponderão perfeitamente ao que você encontrará em software mais recente do que o listado abaixo.

Recomendamos o seguinte hardware e software para este curso:

Antes de começar

Para evitar problemas ao criar este projeto, é altamente recomendável que você crie o projeto neste tutorial em uma pasta raiz ou quase raiz (caminhos de pasta longos podem causar problemas em tempo de compilação).

Aviso

Esteja ciente, os dados que vão para o Application Insights levam tempo, então seja paciente. Se quiser verificar se o Serviço recebeu os seus dados, consulte o Capítulo 14, que lhe mostrará como navegar no portal.

Capítulo 1 - O Portal do Azure

Para usar o Application Insights, você precisará criar e configurar um Serviço do Application Insights no portal do Azure.

  1. Inicie sessão no Portal do Azure.

    Nota

    Se ainda não tiver uma conta do Azure, terá de criar uma. Se você estiver seguindo este tutorial em uma situação de sala de aula ou laboratório, peça ajuda ao seu instrutor ou a um dos proctors para configurar sua nova conta.

  2. Depois de iniciar sessão, clique em Novo no canto superior esquerdo, procure Informações sobre Aplicações e clique em Enter.

    Nota

    A palavra Novo pode ter sido substituída por Criar um recurso, em portais mais recentes.

    Captura de ecrã a mostrar o Portal do Azure, o Insight está realçado no painel Tudo.

  3. A nova página à direita fornecerá uma descrição do Serviço Azure Application Insights . No canto inferior esquerdo desta página, selecione o botão Criar para criar uma associação com este Serviço.

    Captura de tela da tela Application Insights, Create está realçada.

  4. Depois de clicar em Criar:

    1. Insira o Nome desejado para esta instância de Serviço.

    2. Como Tipo de Aplicativo, selecione Geral.

    3. Selecione uma Assinatura apropriada.

    4. Escolha um Grupo de Recursos ou crie um novo. Um grupo de recursos fornece uma maneira de monitorar, controlar o acesso, provisionar e gerenciar a cobrança de uma coleção de ativos do Azure. É recomendável manter todos os Serviços do Azure associados a um único projeto (por exemplo, como esses cursos) em um grupo de recursos comum).

      Se desejar ler mais sobre os Grupos de Recursos do Azure, visite o artigo do grupo de recursos.

    5. Selecione uma Localização.

    6. Também terá de confirmar que compreendeu os Termos e Condições aplicados a este Serviço.

    7. Selecione Criar.

      Captura de ecrã da janela Application Insights. O nome e o tipo de aplicativo são realçados.

  5. Depois de clicar em Criar, você terá que esperar que o Serviço seja criado, isso pode levar um minuto.

  6. Uma notificação aparecerá no portal assim que a instância de serviço for criada.

    Captura de ecrã a mostrar uma parte do friso do menu, o ícone de notificação está realçado.

  7. Selecione as notificações para explorar sua nova instância de serviço.

    Captura de tela mostrando a caixa de diálogo Implantação bem-sucedida, Ir para recurso está realçado.

  8. Clique no botão Ir para recurso na notificação para explorar sua nova instância de serviço. Você será direcionado para sua nova instância do Serviço Application Insights.

    Captura de tela mostrando a instância do Serviço Application Insights onde o nome da instância é MyNewInsight.

    Nota

    Mantenha esta página web aberta e de fácil acesso, você voltará aqui com frequência para ver os dados coletados.

    Importante

    Para implementar o Application Insights, você precisará usar três (3) valores específicos: Chave de instrumentação, ID do aplicativo e Chave da API. Abaixo, você verá como recuperar esses valores do seu Serviço. Certifique-se de anotar esses valores em uma página em branco do Bloco de Notas , porque você os usará em breve em seu código.

  9. Para encontrar a Chave de Instrumentação, você precisará rolar para baixo a lista de funções de Serviço e selecionar Propriedades, a guia exibida revelará a Chave de Serviço.

    Captura de tela mostrando funções de serviço, Propriedades é realçada na seção Configurar e Chave de Instrumentação é realçada no painel principal.

  10. Um pouco abaixo de Propriedades, você encontrará o Acesso à API, no qual você precisa clicar. O painel à direita fornecerá a ID do aplicativo do seu aplicativo.

    Captura de tela mostrando funções de serviço, A P I Access está realçado. Create A P I Key e Application I D são destacados no painel principal.

  11. Com o painel ID do aplicativo ainda aberto, clique em Criar chave de API, que abrirá o painel Criar chave de API.

    Captura de tela mostrando o painel de teclas Criar um P I.

  12. No painel Criar chave de API, agora aberto, digite uma descrição e marque as três caixas.

  13. Clique em Gerar chave. Sua chave de API será criada e exibida.

    Captura de tela do painel de teclas Criar um P I mostrando as informações da nova chave de serviço.

    Aviso

    Esta é a única vez que sua Chave de Serviço será exibida, portanto, certifique-se de fazer uma cópia dela agora.

Capítulo 2 - Configurar o projeto Unity

A seguir está uma configuração típica para desenvolver com a realidade mista e, como tal, é um bom modelo para outros projetos.

  1. Abra o Unity e clique em Novo.

    Captura de tela da janela de projetos Unity. Nenhuma informação do projeto é mostrada.

  2. Agora você precisará fornecer um nome de Projeto Unity, inserir MR_Azure_Application_Insights. Certifique-se de que o Modelo está definido como 3D. Defina o Local para algum lugar apropriado para você (lembre-se, mais perto de diretórios raiz é melhor). Em seguida, clique em Criar projeto.

    Captura de tela da janela Novos projetos do Unity, mostrando informações do projeto.

  3. Com o Unity aberto, vale a pena verificar se o Editor de Scripts padrão está definido como Visual Studio. Vá para Editar > Preferências e, na nova janela, navegue até Ferramentas Externas. Altere o Editor de Scripts Externo para Visual Studio 2017. Feche a janela Preferências .

    Captura de tela mostrando que o Visual Studio está configurado como o editor de scripts externo.

  4. Em seguida, vá para Configurações de compilação de arquivos > e mude a plataforma para a Plataforma Universal do Windows, clicando no botão Alternar plataforma.

    Captura de tela da janela Configurações de compilação, mostrando a lista de seleção de plataforma. A Plataforma Universal do Windows está selecionada.

  5. Vá para Configurações de compilação de arquivo > e certifique-se de que:

    1. O Dispositivo de Destino está definido como Qualquer dispositivo

      Para o Microsoft HoloLens, defina Target Device como HoloLens.

    2. O tipo de compilação está definido como D3D

    3. O SDK está definido como Instalado mais recente

    4. Build and Run está definido como Máquina Local

    5. Salve a cena e adicione-a à compilação.

      1. Faça isso selecionando Adicionar cenas abertas. Será exibida uma janela de salvamento.

        Captura de tela da janela Configurações de compilação, Adicionar cenas abertas está selecionada.

      2. Crie uma nova pasta para esta e qualquer cena futura e, em seguida, clique no botão Nova pasta , para criar uma nova pasta, nomeie-a Cenas.

        Captura de tela da janela Salvar cena, a pasta Cenas está selecionada.

      3. Abra a pasta Cenas recém-criada e, no campo de texto Nome do arquivo:, digite ApplicationInsightsScene e clique em Salvar.

        Captura de ecrã da janela Guardar cena com o nome do ficheiro introduzido.

  6. As configurações restantes, em Configurações de compilação, devem ser deixadas como padrão por enquanto.

  7. Na janela Configurações de Compilação , selecione Configurações do Player, isso abrirá o painel relacionado no espaço onde o Inspetor está localizado.

    Captura de ecrã do separador Inspetor a mostrar as Definições do Jogador.

  8. Neste painel, algumas configurações precisam ser verificadas:

    1. Na guia Outras configurações:

      1. A versão do Scripting Runtime deve ser experimental (equivalente ao .NET 4.6), o que acionará a necessidade de reiniciar o Editor.

      2. O back-end de scripts deve ser .NET

      3. O nível de compatibilidade da API deve ser .NET 4.6

      Captura de tela da guia Inspetor mostrando detalhes na seção de configuração de Outras configurações.

    2. Na guia Configurações de publicação , em Recursos, verifique:

      • InternetClient

        Captura de tela da lista Recursos, cliente de Internet está marcado.

    3. Mais abaixo no painel, em Configurações XR (encontradas abaixo de Configurações de publicação), marque Realidade Virtual suportada, verifique se o SDK de realidade mista do Windows foi adicionado.

      Captura de tela da seção Configurações do X R, Realidade Virtual suportada está marcada.

  9. De volta às Configurações de compilação, o Unity C# Projects não está mais acinzentado, marque a caixa de seleção ao lado disso.

  10. Feche a janela Configurações de compilação.

  11. Salve sua cena e projeto (FILE>SAVE SCENE / FILE>SAVE PROJECT).

Capítulo 3 - Importar o pacote Unity

Importante

Se você deseja ignorar os componentes Unity set deste curso e continuar direto no código, sinta-se à vontade para baixar este pacote Azure-MR-309.unity, importe-o para seu projeto como um pacote personalizado. Isso também conterá as DLLs do próximo capítulo. Após a importação, continuar a partir do Capítulo 6.

Importante

Para usar o Application Insights no Unity, você precisa importar a DLL para ele, juntamente com a DLL Newtonsoft. Atualmente, há um problema conhecido no Unity que exige que os plug-ins sejam reconfigurados após a importação. Essas etapas (4 - 7 nesta seção) não serão mais necessárias depois que o bug for resolvido.

Para importar o Application Insights para o seu próprio projeto, certifique-se de ter baixado o '.unitypackage', que contém os plugins. Em seguida, faça o seguinte:

  1. Adicione o.unitypackage** ao Unity usando a opção de menu Pacote personalizado do pacote > de importação de ativos>.

  2. Na caixa Importar pacote Unity que aparece, verifique se tudo em (e incluindo) Plug-ins está selecionado.

    Captura de tela da caixa de diálogo Importar Pacote Unity mostrando todos os itens marcados.

  3. Clique no botão Importar para adicionar os itens ao seu projeto.

  4. Vá para a pasta Insights em Plug-ins na visualização Projeto e selecione apenas os seguintes plug-ins:

    • Microsoft.ApplicationInsights

    Captura de tela do painel Projeto, a pasta Insights está aberta.

  5. Com este plug-in selecionado, certifique-se de que Any Platform está desmarcada, certifique-se de que o WSAPlayer também está desmarcado e clique em Aplicar. Fazer isso é apenas para confirmar que os arquivos estão configurados corretamente.

    Captura de tela do painel Inspetor mostrando Editor e Autônomo marcados.

    Nota

    Marcando os plugins assim, configura-os para serem usados apenas no Editor Unity. Há um conjunto diferente de DLLs na pasta WSA que será usado depois que o projeto for exportado do Unity.

  6. Em seguida, você precisa abrir a pasta WSA , dentro da pasta Insights . Você verá uma cópia do mesmo arquivo que configurou. Selecione este arquivo e, no inspetor, verifique se Any Platform está desmarcada e, em seguida, verifique se apenas o WSAPlayer está marcado. Clique em Aplicar.

    Captura de ecrã do painel Inspetor a mostrar W S A Player verificado.

  7. Agora você precisará seguir os passos 4-6, mas para os plugins Newtonsoft . Veja a captura de tela abaixo para saber como deve ser o resultado.

    Captura de tela de quatro visualizações dos painéis Project e Inspetor mostrando os resultados da configuração da pasta Newtonsoft e das seleções de plugins.

Capítulo 4 - Configurar a câmara e os controlos do utilizador

Neste capítulo, você configurará a câmera e os controles para permitir que o usuário veja e se mova na cena.

  1. Clique com o botão direito do rato numa área vazia no Painel Hierarquia e, em seguida, em Criar>Vazio.

    Captura de tela do painel Hierarquia, Criar vazio está selecionado.

  2. Renomeie o novo GameObject vazio para Camera Parent.

    Captura de ecrã do painel Hierarquia com a opção Pai da câmara selecionada. O painel Inspetor

  3. Clique com o botão direito do rato numa área vazia no Painel de Hierarquia, depois em Objeto 3D e, em seguida, em Esfera.

  4. Renomeie a esfera para Mão Direita.

  5. Defina a escala de transformação da mão direita como 0,1, 0,1, 0,1

    Captura de tela dos painéis Hierarquia e Inspetor, a seção Transformar no painel Inspetor é realçada.

  6. Remova o componente Sphere Collider da mão direita clicando na engrenagem no componente Sphere Collider e, em seguida, remova o componente.

    A captura de tela do painel Inspetor, o ícone de engrenagem e Remover componente são realçados na seção Colisor de esfera.

  7. No painel Hierarquia, arraste os objetos Câmera principal e Mão direita para o objeto Pai da câmera.

    Captura de tela do painel Hierarquia com a câmera principal selecionada, o painel Inspetor mostra a câmera principal marcada.

  8. Defina a posição de transformação da câmera principal e do objeto da mão direita como 0, 0, 0.

    Captura de tela do painel Hierarquia com a câmera principal selecionada, as configurações de transformação são realçadas no painel Inspetor.

    Captura de tela do painel Hierarquia com a Mão Direita selecionada, as configurações de Transformação são realçadas no painel Inspetor.

Capítulo 5 - Configurar os objetos na cena Unity

Agora você criará algumas formas básicas para sua cena, com as quais o usuário poderá interagir.

  1. Clique com o botão direito do rato numa área vazia no Painel de Hierarquia, depois em Objeto 3D e, em seguida, selecione Plano.

  2. Defina a posição de transformação plana como 0, -1, 0.

  3. Defina a escala de transformação plana como 5, 1, 5.

    Captura de tela dos painéis Cena, Hierarquia e Inspetor. A seção Transformar no painel Inspetor é realçada.

  4. Crie um material básico para usar com seu objeto Plane , para que as outras formas sejam mais fáceis de ver. Navegue até o Painel do Projeto, clique com o botão direito do mouse e, em seguida , em Criar, seguido de Pasta, para criar uma nova pasta. Nomeie-o Materiais.

    Captura de tela do painel Projeto mostrando Criar e Pasta realçada. Captura de tela do painel Projeto. Materiais é realçado no painel Ativos.

  5. Abra a pasta Materiais, clique com o botão direito do mouse, clique em Criar e, em seguida, em Material, para criar um novo material. Nomeie-o Azul.

    Captura de tela do painel Projeto mostrando Criar e Material realçado. Captura de tela do painel Projeto. O azul é realçado no painel Materiais.

  6. Com o novo material azul selecionado, olhe para o Inspetor e clique na janela retangular ao lado de Albedo. Selecione uma cor azul (a imagem abaixo é Hex Color: #3592FFFF). Clique no botão Fechar depois de ter escolhido.

    Captura de tela do painel Inspetor. A seção de cores é realçada.

  7. Arraste o novo material da pasta Materiais para o Plano recém-criado, dentro da cena (ou solte-o no objeto Plano dentro da Hierarquia).

    Captura de tela do painel Cena mostrando o novo material da pasta Materiais.

  8. Clique com o botão direito do rato numa área vazia no Painel de Hierarquia e, em seguida, em Objeto 3D, Cápsula.

    • Com a cápsula selecionada, altere sua posição de transformação para: -10, 1, 0.
  9. Clique com o botão direito do mouse em uma área vazia no Painel de Hierarquia e, em seguida, em Objeto 3D, Cubo.

    • Com o cubo selecionado, altere sua posição de transformação para: 0, 0, 10.
  10. Clique com o botão direito do rato numa área vazia no Painel Hierarquia e, em seguida, em Objeto 3D, Esfera.

    • Com a Esfera selecionada, altere sua Posição de Transformação para: 10, 0, 0.

    Captura de tela dos painéis Cena, Hierarquia e Inspetor. A cápsula é selecionada no painel Hierarquia.

    Nota

    Estes valores de Posição são sugestões. Você é livre para definir as posições dos objetos para o que quiser, embora seja mais fácil para o usuário do aplicativo se as distâncias dos objetos não estiverem muito longe da câmera.

  11. Quando seu aplicativo está em execução, ele precisa ser capaz de identificar os objetos dentro da cena, para conseguir isso, eles precisam ser marcados. Selecione um dos objetos e, no painel Inspetor, clique em Adicionar tag..., que trocará o inspetor pelo painel Tags & Camadas.

    Captura de ecrã do painel Inspetor a mostrar a opção Adicionar etiqueta realçada. Captura de tela do painel Inspetor mostrando Tags e Camadas realçadas.

  12. Clique no símbolo + (mais) e digite o nome da marca como ObjectInScene.

    Captura de ecrã do painel Inspetor com Etiquetas e Camadas selecionadas. A caixa de diálogo Novo nome da marca é realçada.

    Aviso

    Se você usar um nome diferente para sua tag, precisará garantir que essa alteração também seja feita nos scripts DataFromAnalytics, ObjectTrigger e Gaze, posteriormente, para que seus objetos sejam encontrados e detetados em sua cena.

  13. Com a tag criada, agora você precisa aplicá-la a todos os seus três objetos. Na Hierarquia, mantenha pressionada a tecla Shift, clique nos objetos Cápsula, Cubo e Esfera e, em seguida, no Inspetor, clique no menu suspenso ao lado de Tag e, em seguida, clique na marca ObjectInScene que você criou.

    Captura de ecrã do painel Inspetor, uma seta aponta para Etiqueta. O menu Untagged mostra Untagged checked e ObjectInScene está selecionado. Captura de ecrã a mostrar dois menus com Criar e Pasta realçados.

Capítulo 6 - Criar a classe ApplicationInsightsTracker

O primeiro script que você precisa criar é o ApplicationInsightsTracker, que é responsável por:

  1. Criação de eventos com base nas interações do usuário para enviar ao Azure Application Insights.

  2. Criação de nomes de eventos apropriados, dependendo da interação do usuário.

  3. Envio de eventos para a instância do Serviço Application Insights.

Para criar esta classe:

  1. Clique com o botão direito do rato no Painel do Projeto e, em seguida, em Criar> Pasta. Nomeie a pasta Scripts.

    Captura de tela do painel Projetos. O ícone da pasta Scripts é realçado no painel Ativos. Captura de tela mostrando as opções do menu onde as opções Criar e Script C# estão selecionadas.

  2. Com a pasta Scripts criada, clique duas vezes nela para abri-la. Em seguida, dentro dessa pasta, clique com o botão direito do mouse em Criar>script C#. Nomeie o script ApplicationInsightsTracker.

  3. Clique duas vezes no novo script ApplicationInsightsTracker para abri-lo com o Visual Studio.

  4. Atualize os namespaces na parte superior do script para que fiquem como abaixo:

        using Microsoft.ApplicationInsights;
        using Microsoft.ApplicationInsights.DataContracts;
        using Microsoft.ApplicationInsights.Extensibility;
        using UnityEngine;
    
  5. Dentro da classe insira as seguintes variáveis:

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

    Defina os valores instrumentationKey, applicationId e API_Key adequadamente, usando as Chaves de Serviço do Portal do Azure, conforme mencionado no Capítulo 1, etapa 9 em diante.

  6. Em seguida, adicione os métodos Start() e Awake(), que serão chamados quando a classe for inicializada:

        /// <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. Adicione os métodos responsáveis pelo envio dos eventos e métricas cadastrados pelo seu aplicativo:

        /// <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. Certifique-se de salvar suas alterações no Visual Studio antes de retornar ao Unity.

Capítulo 7 - Criar o script Gaze

O próximo script a ser criado é o script Gaze . Este script é responsável por criar um Raycast que será projetado para a frente a partir da câmera principal, para detetar qual objeto o usuário está olhando. Nesse caso, o Raycast precisará identificar se o usuário está olhando para um objeto com a tag ObjectInScene e, em seguida, contar quanto tempo o usuário olha para esse objeto.

  1. Clique duas vezes na pasta Scripts para abri-la.

  2. Clique com o botão direito do mouse dentro da pasta Scripts, clique em Criar>script C#. Nomeie o script como Gaze.

  3. Clique duas vezes no script para abri-lo com o Visual Studio.

  4. Substitua o código existente pelo seguinte:

        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. O código para os métodos Awake() e Start() agora precisa ser adicionado.

        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 da classe Gaze , adicione o seguinte código no método Update() para projetar um Raycast e detetar o alvo atingido:

        /// <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. Adicione o método ResetFocusedObject() para enviar dados para o Application Insights quando o usuário tiver olhado para um 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. Agora você concluiu o roteiro do Gaze . Salve suas alterações no Visual Studio antes de retornar ao Unity.

Capítulo 8 - Criar a classe ObjectTrigger

O próximo script que você precisa criar é ObjectTrigger, que é responsável por:

  • Adicionar componentes necessários para a colisão à câmara principal.
  • Detetar se a câmera está perto de um objeto marcado como ObjectInScene.

Para criar o script:

  1. Clique duas vezes na pasta Scripts para abri-la.

  2. Clique com o botão direito do mouse dentro da pasta Scripts, clique em Criar>script C#. Nomeie o script ObjectTrigger.

  3. Clique duas vezes no script para abri-lo com o Visual Studio. Substitua o código existente pelo seguinte:

        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. Certifique-se de salvar suas alterações no Visual Studio antes de retornar ao Unity.

Capítulo 9 - Criar a classe DataFromAnalytics

Agora você precisará criar o script DataFromAnalytics , que é responsável por:

  • Buscar dados analíticos sobre qual objeto foi mais abordado pela câmera.
  • Usando as chaves de serviço, que permitem a comunicação com sua instância do Serviço Azure Application Insights.
  • Classificando os objetos em cena, de acordo com o que tem a maior contagem de eventos.
  • Alterar a cor do material, do objeto mais abordado, para verde.

Para criar o script:

  1. Clique duas vezes na pasta Scripts para abri-la.

  2. Clique com o botão direito do mouse dentro da pasta Scripts, clique em Criar>script C#. Nomeie o script DataFromAnalytics.

  3. Clique duas vezes no script para abri-lo com o Visual Studio.

  4. Insira os seguintes namespaces:

        using Newtonsoft.Json;
        using System;
        using System.Collections;
        using System.Collections.Generic;
        using System.Linq;
        using UnityEngine;
        using UnityEngine.Networking;
    
  5. Dentro do script, insira o seguinte:

        /// <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 da classe DataFromAnalytics , logo após o método Start(), adicione o seguinte método chamado FetchAnalytics(). Esse método é responsável por preencher a lista de pares de valores de chave, com um GameObject e um número de contagem de eventos de espaço reservado. Em seguida, inicializa a co-rotina GetWebRequest(). A estrutura de consulta da chamada para o Application Insights também pode ser encontrada nesse método, como o ponto de extremidade da 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. Logo abaixo do método FetchAnalytics(), adicione um método chamado GetWebRequest(), que retorna um IEnumerator. Esse método é responsável por solicitar o número de vezes que um evento, correspondente a um GameObject específico, foi chamado dentro do Application Insights. Quando todas as consultas enviadas forem retornadas, o método DetermineWinner() será chamado.

        /// <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. O próximo método é DetermineWinner(), que classifica a lista de pares GameObject e Int, de acordo com a maior contagem de eventos. Em seguida, ele altera a cor do material desse GameObject para verde (como feedback para ele ter a maior contagem). Isso exibe uma mensagem com os resultados da análise.

        /// <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. Adicione a estrutura de classe que será usada para desserializar o objeto JSON, recebido do Application Insights. Adicione essas classes na parte inferior do arquivo de classe DataFromAnalytics , fora da definição de classe.

        /// <summary>
        /// These classes represent the structure of the JSON response from Azure Insight
        /// </summary>
        [Serializable]
        public class Analytics
        {
            [JsonProperty("@odata.context")]
            public string OdataContext { get; set; }
    
            [JsonProperty("@odata.count")]
            public string OdataCount { get; set; }
    
            [JsonProperty("value")]
            public Value[] Value { get; set; }
        }
    
        [Serializable]
        public class Value
        {
            [JsonProperty("customMetric")]
            public CustomMetric CustomMetric { get; set; }
        }
    
        [Serializable]
        public class CustomMetric
        {
            [JsonProperty("name")]
            public string Name { get; set; }
        }
    
  10. Certifique-se de salvar suas alterações no Visual Studio antes de retornar ao Unity.

Capítulo 10 - Criar a classe Movement

O script Movement é o próximo script que você precisará criar. É responsável por:

  • Movendo a câmera principal de acordo com a direção que a câmera está olhando.
  • Adicionar todos os outros scripts a objetos de cena.

Para criar o script:

  1. Clique duas vezes na pasta Scripts para abri-la.

  2. Clique com o botão direito do mouse dentro da pasta Scripts, clique em Criar>script C#. Nomeie o script como Movimento.

  3. Clique duas vezes no script para abri-lo com o Visual Studio.

  4. Substitua o código existente pelo seguinte:

        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 da classe Movement, abaixo do método Update() vazio, insira os seguintes métodos que permitem ao usuário usar o controlador manual para se mover no espaço 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 fim, adicione a chamada de método dentro do método Update( ).

        // Update is called once per frame
        void Update()
        {
            UpdateControllerState();
        }
    
  7. Certifique-se de salvar suas alterações no Visual Studio antes de retornar ao Unity.

Capítulo 11 - Configurando as referências de scripts

Neste capítulo, você precisa colocar o script Movement no pai da câmera e definir seus alvos de referência. Esse script tratará de colocar os outros scripts onde eles precisam estar.

  1. Na pasta Scripts no Painel do projeto, arraste o script Movimento para o objeto pai da câmera, localizado no painel Hierarquia.

    Captura de tela dos painéis Projeto e Hierarquia. O movimento é destacado.

  2. Clique no pai da câmera. No Painel Hierarquia, arraste o objeto Mão Direita do Painel Hierarquia para o destino de referência, Controlador, no Painel Inspetor. Defina a velocidade do usuário para 5, como mostrado na imagem abaixo.

    Captura de tela mostrando os painéis Hierarquia e Inspetor. Uma linha conecta a mão direita em ambos os painéis.

Capítulo 12 - Construir o projeto Unity

Tudo o que era necessário para a seção Unity deste projeto já foi concluído, então é hora de construí-lo a partir de Unity.

  1. Navegue até Configurações de compilação, (Configurações de compilação de arquivo>).

  2. Na janela Configurações de compilação, clique em Compilar.

    Captura de tela da janela Configurações de compilação mostrando cenas na compilação.

  3. Uma janela do Explorador de Arquivos será exibida, solicitando um local para a compilação. Crie uma nova pasta (clicando em Nova pasta no canto superior esquerdo) e nomeie-a como BUILDS.

    Captura de ecrã do Explorador de Ficheiros a mostrar a pasta Compilações realçada.

    1. Abra a nova pasta BUILDS e crie outra pasta (usando New Folder mais uma vez) e nomeie-a MR_Azure_Application_Insights.

      Captura de ecrã do Explorador de ficheiros a mostrar a pasta MR_Azure_Insights.

    2. Com a pasta MR_Azure_Application_Insights selecionada, clique em Selecionar pasta. O projeto levará cerca de um minuto para ser construído.

  4. Após a compilação, o Explorador de Arquivos aparecerá mostrando o local do seu novo projeto.

Capítulo 13 - Implantar MR_Azure_Application_Insights aplicativo em sua máquina

Para implantar o aplicativo MR_Azure_Application_Insights em sua máquina local:

  1. Abra o arquivo de solução do seu aplicativo MR_Azure_Application_Insights no Visual Studio.

  2. Na Plataforma de Solução, selecione x86, Máquina Local.

  3. Na Configuração da Solução, selecione Depurar.

    Captura de tela da tela Configuração da Solução do Visual Studio mostrando Depurar na barra de menus.

  4. Vá para o menu Build e clique em Deploy Solution para fazer sideload do aplicativo para sua máquina.

  5. Seu aplicativo agora deve aparecer na lista de aplicativos instalados, pronto para ser iniciado.

  6. Inicie o aplicativo de realidade mista.

  7. Mova-se pela cena, aproximando-se de objetos e olhando para eles, quando o Serviço Azure Insight tiver coletado dados de evento suficientes, ele definirá o objeto que foi mais abordado como verde.

Importante

Enquanto o tempo médio de espera para que os Eventos e Métricas sejam coletados pelo Serviço leva cerca de 15 minutos, em algumas ocasiões pode levar até 1 hora.

Capítulo 14 - O portal do Serviço Application Insights

Depois de percorrer a cena e olhar para vários objetos, você pode ver os dados coletados no portal do Serviço do Application Insights .

  1. Volte para o portal do Serviço do Application Insights.

  2. Selecione Explorador de Métricas.

    Captura de tela do painel MyNewInsight mostrando a lista de opções. O Metrics Explorer está listado na seção Investigar.

  3. Ele será aberto em uma guia contendo o gráfico, que representa os Eventos e Métricas relacionados ao seu aplicativo. Como mencionado acima, pode levar algum tempo (até 1 hora) para que os dados sejam exibidos no gráfico

    Captura de tela do Metrics Explorer mostrando os eventos e o gráfico de métricas.

  4. Selecione a barra Eventos no Total de Eventos por Versão do Aplicativo para ver um detalhamento detalhado dos eventos com seus nomes.

    Captura de ecrã do painel Pesquisar a mostrar os resultados de um filtro de eventos personalizado.

Seu aplicativo de serviço do Application Insights concluído

Parabéns, você criou um aplicativo de realidade mista que aproveita o Serviço do Application Insights para monitorar a atividade do usuário em seu aplicativo.

Tela de boas-vindas do curso.

Exercícios de Bónus

Exercício 1

Tente gerar, em vez de criar manualmente, os objetos ObjectInScene e defina suas coordenadas no plano dentro de seus scripts. Dessa forma, você pode perguntar ao Azure qual era o objeto mais popular (seja de resultados de olhar ou proximidade) e gerar um extra desses objetos.

Exercício 2

Classifique os resultados do Application Insights por tempo, para obter os dados mais relevantes, e implemente esses dados sensíveis ao tempo em seu aplicativo.