HoloLens (1.ª geração) e Azure 308: Notificações entre dispositivos


Nota

Os tutoriais Mixed Reality Academy foram concebidos com o HoloLens (1.ª geração) e Mixed Reality Headsets Envolventes em mente. Como tal, consideramos importante deixar estes tutoriais em vigor para os programadores que ainda estão à procura de orientação no desenvolvimento desses dispositivos. Estes tutoriais não serão atualizados com os conjuntos de ferramentas ou interações mais recentes que estão a ser utilizados para HoloLens 2. Serão mantidas para continuarem a trabalhar nos dispositivos suportados. Haverá uma nova série de tutoriais que serão publicados no futuro que demonstrarão como desenvolver para HoloLens 2. Este aviso será atualizado com uma ligação para esses tutoriais quando forem publicados.


produto final - iniciar

Neste curso, irá aprender a adicionar capacidades dos Hubs de Notificação a uma aplicação de realidade mista com hubs de notificação do Azure, Tabelas do Azure e Funções do Azure.

Os Hubs de Notificação do Azure são um serviço Microsoft, que permite aos programadores enviar notificações push direcionadas e personalizadas para qualquer plataforma, todas com tecnologia na cloud. Isto pode permitir que os programadores comuniquem com os utilizadores finais ou mesmo comuniquem entre várias aplicações, dependendo do cenário. Para obter mais informações, visite a páginaHubs de Notificação do Azure.

Funções do Azure é um serviço Microsoft, que permite aos programadores executar pequenos blocos de código, "funções", no Azure. Isto fornece uma forma de delegar trabalho para a cloud, em vez da sua aplicação local, que pode ter muitas vantagens. Funções do Azure suporta várias linguagens de desenvolvimento, incluindo C#, F#, Node.js, Java e PHP. Para obter mais informações, visite a página Funções do Azure.

As Tabelas do Azure são um serviço cloud da Microsoft, que permite aos programadores armazenar dados estruturados não SQL na cloud, tornando-os facilmente acessíveis em qualquer lugar. O serviço possui um design sem esquema, permitindo a evolução das tabelas conforme necessário e, portanto, é muito flexível. Para obter mais informações, visite a páginaTabelas do Azure

Depois de concluir este curso, terá uma aplicação de headset envolvente de realidade mista e uma aplicação de PC de Ambiente de Trabalho, que poderá fazer o seguinte:

  1. A aplicação PC de Ambiente de Trabalho permitirá que o utilizador mova um objeto num espaço 2D (X e Y), utilizando o rato.

  2. O movimento de objetos na aplicação do PC será enviado para a cloud através de JSON, que terá a forma de uma cadeia, que contém um ID de objeto, tipo e informações de transformação (coordenadas X e Y).

  3. A aplicação de realidade mista, que tem uma cena idêntica à aplicação de ambiente de trabalho, receberá notificações relativas ao movimento de objetos, do serviço Notification Hubs (que acabou de ser atualizado pela aplicação pc de secretária).

  4. Após receber uma notificação, que irá conter o ID do objeto, o tipo e as informações de transformação, a aplicação de realidade mista aplicará as informações recebidas à sua própria cena.

Na sua aplicação, cabe-lhe a si saber como irá integrar os resultados com a sua estrutura. Este curso foi concebido para lhe ensinar a integrar um Serviço do Azure no seu Projeto do Unity. A sua função é utilizar o conhecimento obtido neste curso para melhorar a sua aplicação de realidade mista. Este curso é um tutorial autónomo, que não envolve diretamente nenhum outro Mixed Reality Labs.

Suporte de dispositivos

Curso HoloLens Headsets envolventes
MR e Azure 308: Notificações entre dispositivos ✔️ ✔️

Nota

Embora este curso se centre principalmente em headsets envolventes (VR) Windows Mixed Reality, também pode aplicar o que aprendeu neste curso para Microsoft HoloLens. À medida que acompanha o curso, verá notas sobre quaisquer alterações que possa ter de utilizar para suportar o HoloLens. Ao utilizar o HoloLens, poderá notar algum eco durante a captura de voz.

Pré-requisitos

Nota

Este tutorial foi concebido para programadores com experiência básica com o Unity e C#. Tenha também em atenção que os pré-requisitos e as instruções escritas neste documento representam o que foi testado e verificado no momento da escrita (maio de 2018). Pode utilizar 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 encontrará no software mais recente do que o que está listado abaixo.

Recomendamos o seguinte hardware e software para este curso:

Antes de começar

  • Para evitar problemas ao criar este projeto, é altamente sugerido que crie o projeto mencionado neste tutorial numa pasta raiz ou de raiz próxima (os caminhos de pasta longos podem causar problemas no tempo de compilação).
  • Tem de ser o proprietário do Portal do Programador da Microsoft e do Portal de Registo de Aplicações. Caso contrário, não terá permissão para aceder à aplicação no Capítulo 2.

Capítulo 1 - Criar uma aplicação no Portal do Programador da Microsoft

Para utilizar o Serviço hubs de notificação do Azure , terá de criar uma Aplicação no Portal do Programador da Microsoft, uma vez que a sua aplicação terá de ser registada, para que possa enviar e receber notificações.

  1. Inicie sessão no Portal do Programador da Microsoft.

    Terá de iniciar sessão na sua Conta Microsoft.

  2. No Dashboard, clique em Criar uma nova aplicação.

    criar uma aplicação

  3. Será apresentado um pop-up, no qual tem de reservar um nome para a sua nova aplicação. Na caixa de texto, insira um nome adequado; Se o nome escolhido estiver disponível, será apresentado um tique à direita da caixa de texto. Assim que tiver um nome disponível inserido, clique no botão Reservar nome do produto na parte inferior esquerda do pop-up.

    inverter um nome

  4. Com a aplicação agora criada, está pronto para avançar para o capítulo seguinte.

Capítulo 2 – Obter as credenciais das novas aplicações

Inicie sessão no Portal de Registo de Aplicações, onde a sua nova aplicação será listada, e obtenha as credenciais que serão utilizadas para configurar o Serviço notification Hubs no portal do Azure.

  1. Navegue para o Portal de Registo de Aplicações.

    portal de registo de aplicações

    Aviso

    Terá de utilizar a sua Conta Microsoft para Iniciar Sessão.
    Esta tem de ser a Conta Microsoft que utilizou no Capítulo anterior, com o portal para Programadores da Loja Windows.

  2. Encontrará a sua aplicação na secção As minhas aplicações . Depois de o encontrar, clique no mesmo e será levado para uma nova página com o nome da aplicação mais Registo.

    a sua aplicação recentemente registada

  3. Desloque-se para baixo na página de registo para encontrar a secção Segredos da Aplicação e o SID do Pacote para a sua aplicação. Copie ambos para utilização com a configuração do Serviço hubs de notificação do Azure no capítulo seguinte.

    segredos da aplicação

Capítulo 3 - Configurar o Portal do Azure: criar o Serviço hubs de notificação

Com as credenciais das aplicações obtidas, terá de aceder ao Portal do Azure, onde irá criar um Serviço dos Hubs de Notificação 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 estiver a seguir este tutorial numa situação de sala de aula ou laboratório, peça ajuda ao seu instrutor ou a um dos tutores para configurar a sua nova conta.

  2. Assim que tiver sessão iniciada, clique em Novo no canto superior esquerdo, procure Notification Hub e clique em Enter.

    procurar hub de notificação

    Nota

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

  3. A nova página irá fornecer uma descrição do serviço Notification Hubs . Na parte inferior esquerda deste pedido, selecione o botão Criar para criar uma associação com este serviço.

    criar instância dos hubs de notificação

  4. Depois de clicar em Criar:

    1. Insira o nome pretendido para esta instância de serviço.

    2. Forneça um espaço de nomes que poderá associar a esta aplicação.

    3. Selecione uma Localização.

    4. Escolha um Grupo de Recursos ou crie um novo. Um grupo de recursos fornece uma forma de monitorizar, controlar o acesso, aprovisionar e gerir a faturação de uma coleção de recursos do Azure. Recomenda-se manter todos os serviços do Azure associados a um único projeto (por exemplo, estes laboratórios) num grupo de recursos comum.

      Se quiser ler mais sobre os Grupos de Recursos do Azure, siga esta ligação sobre como gerir um Grupo de Recursos.

    5. Selecione uma Subscrição adequada.

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

    7. Selecione Criar.

      preencher os detalhes do serviço

  5. Depois de clicar em Criar, terá de aguardar que o serviço seja criado, o que poderá demorar um minuto.

  6. Será apresentada uma notificação no portal assim que a instância do Serviço for criada.

    notificação

  7. Clique no botão Ir para recurso na notificação para explorar a nova instância do Serviço. Será levado para a nova instância de serviço do Hub de Notificação .

    Captura de ecrã a mostrar o botão

  8. Na página de descrição geral, a meio da página, clique em Windows (WNS). O painel à direita será alterado para mostrar dois campos de texto, que requerem o SID do Pacote e a Chave de Segurança, da aplicação que configurou anteriormente.

    serviço hubs recém-criado

  9. Depois de copiar os detalhes para os campos corretos, clique em Guardar e receberá uma notificação quando o Hub de Notificação tiver sido atualizado com êxito.

    copiar detalhes de segurança

Capítulo 4 - Configurar o Portal do Azure: criar o Serviço Tabela

Depois de criar a instância do Serviço notification Hubs, navegue de volta para o portal do Azure, onde irá criar um Serviço de Tabelas do Azure ao criar um Recurso de Armazenamento.

  1. Se ainda não tiver iniciado sessão, inicie sessão no portal do Azure.

  2. Depois de iniciar sessão, clique em Novo no canto superior esquerdo, procure Conta de armazenamento e clique em Enter.

    Nota

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

  3. Selecione Conta de armazenamento – blob, ficheiro, tabela, fila na lista.

    procurar conta de armazenamento

  4. A nova página irá fornecer uma descrição do serviço Conta de armazenamento . Na parte inferior esquerda deste pedido, selecione o botão Criar para criar uma instância deste serviço.

    criar instância de armazenamento

  5. Depois de clicar em Criar, será apresentado um painel:

    1. Insira o Nome pretendido para esta instância de serviço (tem de estar em minúsculas).

    2. Em Modelo de implementação, clique em Gestor de recursos.

    3. Em Tipo de conta, através do menu pendente, selecione Armazenamento (fins gerais v1).

    4. Selecione uma Localização adequada.

    5. No menu pendente Replicação , selecione Armazenamento georredundante com acesso de leitura (RA-GRS).

    6. Em Desempenho, clique em Standard.

    7. Na secção Transferência segura necessária , selecione Desativado.

    8. No menu pendente Subscrição , selecione uma subscrição adequada.

    9. Escolha um Grupo de Recursos ou crie um novo. Um grupo de recursos fornece uma forma de monitorizar, controlar o acesso, aprovisionar e gerir a faturação de uma coleção de recursos do Azure. Recomenda-se manter todos os serviços do Azure associados a um único projeto (por exemplo, estes laboratórios) num grupo de recursos comum.

      Se quiser ler mais sobre os Grupos de Recursos do Azure, siga esta ligação sobre como gerir um Grupo de Recursos.

    10. Deixe Redes virtuais como Desativadas se esta for uma opção para si.

    11. Clique em Criar.

      preencher detalhes de armazenamento

  6. Depois de clicar em Criar, terá de aguardar que o serviço seja criado, o que poderá demorar um minuto.

  7. Será apresentada uma notificação no portal assim que a instância do Serviço for criada. Clique nas notificações para explorar a nova instância do Serviço.

    nova notificação de armazenamento

  8. Clique no botão Ir para recurso na notificação para explorar a nova instância do Serviço. Será levado para a nova página de descrição geral da instância do Serviço de Armazenamento.

    Captura de ecrã a mostrar o botão

  9. Na página de descrição geral, no lado direito, clique em Tabelas.

    Captura de ecrã que mostra onde selecionar Tabelas.

  10. O painel à direita será alterado para mostrar as informações do serviço Tabela , onde tem de adicionar uma nova tabela. Para tal, clique no + botão Tabela no canto superior esquerdo.

    abrir Tabelas

  11. Será apresentada uma nova página, na qual tem de introduzir um Nome da tabela. Este é o nome que irá utilizar para fazer referência aos dados na sua aplicação em Capítulos posteriores. Insira um nome adequado e clique em OK.

    criar nova tabela

  12. Assim que a nova tabela tiver sido criada, poderá vê-la na página de serviço Tabela (na parte inferior).

    nova tabela criada

Capítulo 5 – Concluir a Tabela do Azure no Visual Studio

Agora que a conta de armazenamento do serviço Tabela foi configurada, está na altura de adicionar dados à mesma, que serão utilizados para armazenar e obter informações. A edição das tabelas pode ser feita através do Visual Studio.

  1. Abra o Visual Studio.

  2. No menu, clique em Ver>Cloud Explorer.

    abrir o explorador de cloud

  3. O Cloud Explorer será aberto como um item ancorado (seja paciente, uma vez que o carregamento pode demorar algum tempo).

    Nota

    Se a Subscrição que utilizou para criar as suas Contas de Armazenamento não estiver visível, certifique-se de que tem:

    • Iniciou sessão na mesma conta que utilizou no portal do Azure.

    • Selecionou a sua Subscrição na Página de Gestão de Contas (poderá ter de aplicar um filtro a partir das definições da sua conta):

      localizar subscrição

  4. Os seus serviços cloud do Azure serão apresentados. Localize Contas de Armazenamento e clique na seta à esquerda para expandir as suas contas.

    abrir contas de armazenamento

  5. Uma vez expandida, a conta de Armazenamento recém-criada deverá estar disponível. Clique na seta à esquerda do seu armazenamento e, em seguida, uma vez expandido, localize Tabelas e clique na seta junto a essa, para revelar a Tabela que criou no último Capítulo. Faça duplo clique na tabela.

    abrir tabela de objetos de cena

  6. A tabela será aberta no centro da janela do Visual Studio. Clique no ícone de tabela com o + (mais) no mesmo.

    adicionar nova tabela

  7. Será apresentada uma janela a pedir-lhe para Adicionar Entidade. Irá criar três entidades no total, cada uma com várias propriedades. Irá reparar que PartitionKey e RowKey já estão fornecidos, uma vez que estes são utilizados pela tabela para localizar os seus dados.

    partição e chave de linha

  8. Atualize o Valor de PartitionKey e RowKey da seguinte forma (lembre-se de o fazer para cada propriedade de linha que adicionar, embora incremente a RowKey de cada vez):

    adicionar Valores corretos

  9. Clique em Adicionar propriedade para adicionar linhas adicionais de dados. Faça com que a sua primeira tabela vazia corresponda à tabela abaixo.

  10. Clique em OK quando terminar.

    clique em OK quando terminar

    Aviso

    Certifique-se de que alterou o Tipo das entradas X, Y e Z para Duplo.

  11. Irá reparar que a sua tabela tem agora uma linha de dados. Clique novamente no + ícone (mais) para adicionar outra entidade.

    primeira linha

  12. Crie uma propriedade adicional e, em seguida, defina os valores da nova entidade para corresponder aos apresentados abaixo.

    adicionar cubo

  13. Repita o último passo para adicionar outra entidade. Defina os valores para esta entidade para os apresentados abaixo.

    adicionar cilindro

  14. A sua tabela deverá agora ter o aspeto da tabela abaixo.

    tabela concluída

  15. Concluiu este Capítulo. Certifique-se de que guarda.

Capítulo 6 - Criar uma Aplicação de Funções do Azure

Crie uma Aplicação de Funções do Azure, que será chamada pela aplicação de Ambiente de Trabalho para atualizar o serviço Tabela e enviar uma notificação através do Hub de Notificação.

Primeiro, tem de criar um ficheiro que permita que a Função do Azure carregue as bibliotecas de que precisa.

  1. Abra o Bloco de Notas (prima a Tecla Windows e escreva bloco de notas).

    abrir bloco de notas

  2. Com o Bloco de Notas aberto, insira a estrutura JSON abaixo na mesma. Depois de o fazer, guarde-o no seu ambiente de trabalho como project.json. É importante que a nomenclatura esteja correta: certifique-se de que NÃO tem uma extensão de ficheiro .txt. Este ficheiro define as bibliotecas que a sua função irá utilizar, se tiver utilizado o NuGet, parecerá familiar.

    {
    "frameworks": {
        "net46":{
        "dependencies": {
            "WindowsAzure.Storage": "7.0.0",
            "Microsoft.Azure.NotificationHubs" : "1.0.9",
            "Microsoft.Azure.WebJobs.Extensions.NotificationHubs" :"1.1.0"
        }
        }
    }
    }
    
  3. Inicie sessão no Portal do Azure.

  4. Assim que tiver sessão iniciada, clique em Novo no canto superior esquerdo e procure Function App, prima Enter.

    procurar aplicação de funções

    Nota

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

  5. A nova página irá fornecer uma descrição do serviço Function App . Na parte inferior esquerda deste pedido, selecione o botão Criar para criar uma associação com este serviço.

    instância da aplicação de funções

  6. Depois de clicar em Criar, preencha o seguinte:

    1. Em Nome da aplicação, insira o nome pretendido para esta instância de serviço.

    2. Selecione uma Subscrição.

    3. Selecione o escalão de preço adequado para si. Se esta for a primeira vez que cria uma Função Serviço de Aplicações, deverá estar disponível um escalão gratuito para si.

    4. Escolha um Grupo de Recursos ou crie um novo. Um grupo de recursos fornece uma forma de monitorizar, controlar o acesso, aprovisionar e gerir a faturação de uma coleção de recursos do Azure. Recomenda-se manter todos os serviços do Azure associados a um único projeto (por exemplo, estes laboratórios) num grupo de recursos comum.

      Se quiser ler mais sobre os Grupos de Recursos do Azure, siga esta ligação sobre como gerir um Grupo de Recursos.

    5. Para SO, clique em Windows, uma vez que é a plataforma pretendida.

    6. Selecione um Plano de Alojamento (este tutorial está a utilizar um Plano de Consumo.

    7. Selecione uma Localização(escolha a mesma localização que o armazenamento que criou no passo anterior)

    8. Para a secção Armazenamento , tem de selecionar o Serviço de Armazenamento que criou no passo anterior.

    9. Não irá precisar do Application Insights nesta aplicação, por isso, não hesite em deixá-lo Desativado.

    10. Clique em Criar.

      criar nova instância

  7. Depois de clicar em Criar , terá de aguardar que o serviço seja criado, o que poderá demorar um minuto.

  8. Será apresentada uma notificação no portal assim que a instância do Serviço for criada.

    nova notificação

  9. Clique nas notificações para explorar a nova instância do Serviço.

  10. Clique no botão Ir para recurso na notificação para explorar a nova instância do Serviço.

    Captura de ecrã a mostrar

  11. Clique no + ícone (mais) junto a Funções, para Criar novo.

    adicionar nova função

  12. No painel central, será apresentada a janela de criação da Função . Ignore as informações na metade superior do painel e clique em Função personalizada, que está localizada perto da parte inferior (na área azul, como abaixo).

    função personalizada

  13. A nova página na janela irá mostrar vários tipos de funções. Desloque-se para baixo para ver os tipos roxos e clique no elemento HTTP PUT .

    http put link

    Importante

    Poderá ter de deslocar mais para baixo na página (e esta imagem pode não ter exatamente o mesmo aspeto, se tiverem ocorrido atualizações do Portal do Azure), no entanto, está à procura de um elemento chamado HTTP PUT.

  14. Será apresentada a janela HTTP PUT , onde tem de configurar a função (veja abaixo para obter a imagem).

    1. Em Idioma, através do menu pendente, selecione C#.

    2. Em Nome, introduza um nome adequado.

    3. No menu pendente Nível de autenticação , selecione Função.

    4. Para a secção Nome da tabela, tem de utilizar o nome exato que utilizou para criar o serviço Tabela anteriormente (incluindo as mesmas maiúsculas/minúsculas).

    5. Na secção Ligação da conta de armazenamento , utilize o menu pendente e selecione a sua conta de armazenamento a partir daí. Se não estiver lá, clique na hiperligação Novo juntamente com o título da secção para mostrar outro painel, onde a sua conta de armazenamento deve estar listada.

      Captura de ecrã a mostrar a secção Ligação da conta de armazenamento com a hiperligação

  15. Clique em Criar e receberá uma notificação a informar que as suas definições foram atualizadas com êxito.

    criar função

  16. Depois de clicar em Criar, será redirecionado para o editor de funções.

    atualizar código de função

  17. Insira o seguinte código no editor de funções (substituindo o código na função):

    #r "Microsoft.WindowsAzure.Storage"
    
    using System;
    using Microsoft.WindowsAzure.Storage;
    using Microsoft.WindowsAzure.Storage.Table;
    using Microsoft.Azure.NotificationHubs;
    using Newtonsoft.Json;
    
    public static async Task Run(UnityGameObject gameObj, CloudTable table, IAsyncCollector<Notification> notification, TraceWriter log)
    {
        //RowKey of the table object to be changed
        string rowKey = gameObj.RowKey;
    
        //Retrieve the table object by its RowKey
        TableOperation operation = TableOperation.Retrieve<UnityGameObject>("UnityPartitionKey", rowKey); 
    
        TableResult result = table.Execute(operation);
    
        //Create a UnityGameObject so to set its parameters
        UnityGameObject existingGameObj = (UnityGameObject)result.Result; 
    
        existingGameObj.RowKey = rowKey;
        existingGameObj.X = gameObj.X;
        existingGameObj.Y = gameObj.Y;
        existingGameObj.Z = gameObj.Z;
    
        //Replace the table appropriate table Entity with the value of the UnityGameObject
        operation = TableOperation.Replace(existingGameObj); 
    
        table.Execute(operation);
    
        log.Verbose($"Updated object position");
    
        //Serialize the UnityGameObject
        string wnsNotificationPayload = JsonConvert.SerializeObject(existingGameObj);
    
        log.Info($"{wnsNotificationPayload}");
    
        var headers = new Dictionary<string, string>();
    
        headers["X-WNS-Type"] = @"wns/raw";
    
        //Send the raw notification to subscribed devices
        await notification.AddAsync(new WindowsNotification(wnsNotificationPayload, headers)); 
    
        log.Verbose($"Sent notification");
    }
    
    // This UnityGameObject represent a Table Entity
    public class UnityGameObject : TableEntity
    {
        public string Type { get; set; }
        public double X { get; set; }
        public double Y { get; set; }
        public double Z { get; set; }
        public string RowKey { get; set; }
    }
    

    Nota

    Com as bibliotecas incluídas, a função recebe o nome e a localização do objeto que foi movido na cena do Unity (como um objeto C#, denominado UnityGameObject). Em seguida, este objeto é utilizado para atualizar os parâmetros de objeto na tabela criada. Depois disso, a função faz uma chamada para o serviço Notification Hub criado, que notifica todas as aplicações subscritas.

  18. Com o código implementado, clique em Guardar.

  19. Em seguida, clique no < ícone (seta), no lado direito da página.

    abrir painel de carregamento

  20. Um painel irá deslizar a partir da direita. Nesse painel, clique em Carregar e será apresentado um Browser de Ficheiros.

  21. Navegue para e clique no ficheiro project.json , que criou anteriormente no Bloco de Notas e, em seguida, clique no botão Abrir . Este ficheiro define as bibliotecas que a sua função irá utilizar.

    carregar json

  22. Quando o ficheiro for carregado, será apresentado no painel à direita. Clicar no mesmo irá abri-lo no Editor de funções . Tem de ter exatamente o mesmo aspeto que a imagem seguinte (abaixo do passo 23).

  23. Em seguida, no painel à esquerda, por baixo de Funções, clique na ligação Integrar .

    integrar função

  24. Na página seguinte, no canto superior direito, clique em Editor avançado (como abaixo).

    abrir editor avançado

  25. Será aberto um ficheiro function.json no painel central, que tem de ser substituído pelo fragmento de código seguinte. Isto define a função que está a criar e os parâmetros transmitidos para a função.

    {
    "bindings": [
        {
        "authLevel": "function",
        "type": "httpTrigger",
        "methods": [
            "get",
            "post"
        ],
        "name": "gameObj",
        "direction": "in"
        },
        {
        "type": "table",
        "name": "table",
        "tableName": "SceneObjectsTable",
        "connection": "mrnothubstorage_STORAGE",
        "direction": "in"
        },
        {
        "type": "notificationHub",
        "direction": "out",
        "name": "notification",
        "hubName": "MR_NotHub_ServiceInstance",
        "connection": "MRNotHubNS_DefaultFullSharedAccessSignature_NH",
        "platform": "wns"
        }
    ]
    }
    
  26. O editor deverá agora ter o aspeto da imagem abaixo:

    voltar ao editor padrão

  27. Poderá reparar que os parâmetros de entrada que acabou de inserir podem não corresponder à tabela e aos detalhes de armazenamento, pelo que terão de ser atualizados com as suas informações. Não faça isto aqui, pois é abordado a seguir. Basta clicar na ligação Editor padrão , no canto superior direito da página, para voltar atrás.

  28. Novamente no editor Standard, clique em Armazenamento de Tabelas do Azure (tabela), em Entradas.

    Entradas de tabela

  29. Certifique-se de que o seguinte corresponde às suas informações, uma vez que podem ser diferentes (existe uma imagem abaixo dos seguintes passos):

    1. Nome da tabela: o nome da tabela que criou no serviço Armazenamento do Azure, Tabelas.

    2. Ligação da conta de armazenamento: clique em nova, que é apresentada juntamente com o menu pendente e será apresentado um painel à direita da janela.

      Captura de ecrã que mostra a janela Conta de Armazenamento com

      1. Selecione a sua Conta de Armazenamento, que criou anteriormente para alojar as Aplicações de Funções.

      2. Irá reparar que o valor de ligação da Conta de Armazenamento foi criado.

      3. Certifique-se de que prime Guardar assim que terminar.

    3. A página Entradas deve agora corresponder à seguinte, mostrando as suas informações.

      entradas concluídas

  30. Em seguida, clique em Hub de Notificação do Azure (notificação) - em Saídas. Certifique-se de que as seguintes informações correspondem às suas informações, uma vez que podem ser diferentes (existe uma imagem abaixo dos seguintes passos):

    1. Nome do Hub de Notificação: este é o nome da sua instância de serviço do Hub de Notificação , que criou anteriormente.

    2. Ligação do espaço de nomes dos Hubs de Notificação: clique em novo, que é apresentado juntamente com o menu pendente.

      verificar saídas

    3. O pop-up Ligação será apresentado (veja a imagem abaixo), onde terá de selecionar o Espaço de Nomes do Hub de Notificação, que configurou anteriormente.

    4. Selecione o nome do Hub de Notificação no menu pendente do meio.

    5. Defina o menu pendente Política como DefaultFullSharedAccessSignature.

    6. Clique no botão Selecionar para voltar atrás.

      atualização de saída

  31. A página Saídas deve agora corresponder às informações abaixo, mas sim às suas informações. Certifique-se de que prime Guardar.

Aviso

Não edite o nome do Hub de Notificação diretamente (tudo isto deve ser feito com o Editor Avançado, desde que tenha seguido os passos anteriores corretamente.

Captura de ecrã que mostra a página Saídas com informações gerais.

  1. Neste momento, deve testar a função para garantir que está a funcionar. Para efetuar este procedimento:

    1. Navegue para a página de funções mais uma vez:

      Captura de ecrã que mostra a página de funções com a função recentemente criada realçada.

    2. Novamente na página de funções, clique no separador Teste , no lado direito da página, para abrir o painel Teste :

      Captura de ecrã da página de funções com

    3. Na caixa de texto Corpo do pedido do painel, cole o código abaixo:

      {  
          "Type":null,
          "X":3,
          "Y":0,
          "Z":1,
          "PartitionKey":null,
          "RowKey":"Obj2",
          "Timestamp":"0001-01-01T00:00:00+00:00",
          "ETag":null
      }
      
    4. Com o código de teste implementado, clique no botão Executar na parte inferior direita e o teste será executado. Os registos de saída do teste serão apresentados na área da consola, abaixo do código da função.

      Captura de ecrã que mostra os registos de saída do teste na área da consola.

    Aviso

    Se o teste acima falhar, terá de verificar novamente se seguiu exatamente os passos acima, em particular as definições no painel de integração.

Capítulo 7 - Configurar o Projeto unity de ambiente de trabalho

Importante

A aplicação Ambiente de Trabalho que está a criar não funcionará no Editor do Unity. Tem de ser executado fora do Editor, seguindo o Edifício da aplicação, utilizando o Visual Studio (ou a aplicação implementada).

Segue-se uma configuração típica para o desenvolvimento com o Unity e a realidade mista e, como tal, é um bom modelo para outros projetos.

Configure e teste os auscultadores envolventes de realidade mista.

Nota

Não irá precisar de Controladores de Movimento para este curso. Se precisar de suporte para configurar o headset envolvente, siga esta ligação sobre como configurar Windows Mixed Reality.

  1. Abra o Unity e clique em Novo.

    Captura de ecrã da janela Projetos do Unity com o ícone de projeto

  2. Tem de fornecer um nome de Projeto do Unity, inserir UnityDesktopNotifHub. Certifique-se de que o tipo de projeto está definido como 3D. Defina a Localização para um local adequado para si (lembre-se de que é melhor estar mais perto dos diretórios de raiz). Em seguida, clique em Criar projeto.

    criar projeto

  3. Com o Unity aberto, vale a pena verificar se o Editor de Scripts predefinido está definido como Visual Studio. Aceda a Editar>Preferências e, em seguida, a partir da nova janela, navegue para Ferramentas Externas. Altere o Editor de Scripts Externos para o Visual Studio 2017. Feche a janela Preferências .

    definir ferramentas VS externas

  4. Em seguida, aceda aDefinições de Compilação de Ficheiros> e selecione Plataforma Universal do Windows e, em seguida, clique no botão Mudar de Plataforma para aplicar a sua seleção.

    mudar de plataforma

  5. Ainda emDefinições de Compilação de Ficheiros>, certifique-se de que:

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

      Esta Aplicação será para o seu ambiente de trabalho, pelo que tem de ser Qualquer Dispositivo

    2. O Tipo de Compilação está definido como D3D

    3. O SDK está definido como Instalado mais recentemente

    4. A Versão do Visual Studio está definida como Mais Recente instalada

    5. A compilação e a execução estão definidas como Máquina Local

    6. Enquanto estiver aqui, vale a pena guardar a cena e adicioná-la à compilação.

      1. Faça-o ao selecionar Adicionar Cenas Abertas. Será apresentada uma janela guardar.

        Captura de ecrã que mostra a opção

      2. Crie uma nova pasta para este cenário e, em seguida, selecione o botão Nova pasta , para criar uma nova pasta, atribua-lhe o nome Cenas.

        Captura de ecrã a mostrar uma nova pasta Cenas criada com

      3. Abra a pasta Cenas recentemente criada e, em seguida, no campo Nome do ficheiro : texto, escreva NH_Desktop_Scene e, em seguida, prima Guardar.

        nova NH_Desktop_Scene

    7. As restantes definições, em Definições de Compilação, devem ser deixadas como predefinição por enquanto.

  6. Na mesma janela, clique no botão Definições do Leitor , este procedimento abrirá o painel relacionado no espaço onde o Inspetor está localizado.

  7. Neste painel, é necessário verificar algumas definições:

    1. No separador Outras Definições :

      1. A Versão do Runtime de Scripting deve ser Experimental (.NET 4.6 Equivalente)

      2. O Back-end de Scripts deve ser .NET

      3. O Nível de Compatibilidade da API deve ser .NET 4.6

        Versão 4.6 net

    2. No separador Definições de Publicação , em Capacidades, verifique:

      • InternetClient

        Captura de ecrã que mostra InternetClient selecionado em Capacidades.

  8. Novamente em Definições de Compilação, o Unity C# Projects já não está a cinzento; marque a caixa de verificação junto a esta.

  9. Feche a janela Definições de Compilação .

  10. Guarde a Cena e a Cena de Gravação de Ficheiros> do Projeto/Projeto de Gravaçãode Ficheiros>.

    Importante

    Se quiser ignorar o componente Configurar o Unity para este projeto (Aplicação de Ambiente de Trabalho) e continuar diretamente para o código, pode transferir este .unitypackage, importá-lo para o seu projeto como Um Pacote Personalizado e, em seguida, continuar a partir do Capítulo 9. Ainda terá de adicionar os componentes do script.

Capítulo 8 – Importar os DLLs no Unity

Irá utilizar o Armazenamento do Azure para o Unity (que, por si só, tira partido do SDK .Net para o Azure). Para obter mais informações, siga esta ligação sobre o Armazenamento do Azure para o Unity.

Existe atualmente um problema conhecido no Unity que requer que os plug-ins sejam reconfigurados após a importação. Estes passos (4 a 7 nesta secção) deixarão de ser necessários após a resolução do erro.

Para importar o SDK para o seu próprio projeto, certifique-se de que transferiu o .unitypackage mais recente a partir do GitHub. Em seguida, faça o seguinte:

  1. Adicione o .unitypackage ao Unity com a opção de menu Pacote Personalizado Importar Pacote > de Importação de Recursos>.

  2. Na caixa Importar Pacote do Unity que é apresentada, pode selecionar tudo em Armazenamento de Plug-in>. Desmarque tudo o resto, uma vez que não é necessário para este curso.

    importar para o pacote

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

  4. Aceda à pasta Armazenamento em Plug-ins na vista Projeto e selecione apenas os seguintes plug-ins:

    • Microsoft.Data.Edm
    • Microsoft.Data.OData
    • Microsoft.WindowsAzure.Storage
    • Newtonsoft.Json
    • System.Spatial

desmarque Qualquer plataforma

  1. Com estes plug-ins específicos selecionados,desmarqueQualquer Plataforma e desmarqueWSAPlayer e, em seguida, clique em Aplicar.

    aplicar dlls de plataforma

    Nota

    Estamos a marcar estes plug-ins específicos para serem utilizados apenas no Editor do Unity. Isto acontece porque existem versões diferentes dos mesmos plug-ins na pasta WSA que serão utilizadas depois de o projeto ser exportado do Unity.

  2. Na pasta Plug-in de armazenamento , selecione apenas:

    • Microsoft.Data.Services.Client

      definir não processar para dlls

  3. Selecione a caixa Não Processar em Definições da Plataforma e clique em Aplicar.

    não aplicar processamento

    Nota

    Estamos a marcar este plug-in "Não processe", porque o patcher de assemblagem do Unity tem dificuldade em processar este plug-in. O plug-in continuará a funcionar mesmo que não seja processado.

Capítulo 9 - Criar a classe TableToScene no projeto Unity de Ambiente de Trabalho

Agora tem de criar os scripts que contêm o código para executar esta aplicação.

O primeiro script que precisa de criar é TableToScene, que é responsável por:

  • Ler entidades na Tabela do Azure.
  • Com os dados da Tabela, determine quais os objetos a gerar e em que posição.

O segundo script que precisa de criar é o CloudScene, que é responsável por:

  • Registar o evento de clique com o botão esquerdo do rato, para permitir que o utilizador arraste objetos em torno do cenário.
  • Serializar os dados do objeto a partir desta cena do Unity e enviá-lo para a Aplicação de Funções do Azure.

Para criar esta classe:

  1. Clique com o botão direito do rato na Pasta de Recursos localizada no Painel de Projeto, Criar>Pasta. Atribua um nome aos Scripts da pasta.

    criar pasta de scripts

    criar pasta de scripts 2

  2. Faça duplo clique na pasta que acabou de criar para abri-la.

  3. Clique com o botão direito do rato dentro da pasta Scripts e clique em Criar>Script C#. Atribua o nome TableToScene ao script.

    Captura de ecrã que mostra como criar o novo script Mudar o nome de TableToScene

  4. Faça duplo clique no script para o abrir no Visual Studio 2017.

  5. Adicione os seguintes espaços de nomes:

    using Microsoft.WindowsAzure.Storage;
    using Microsoft.WindowsAzure.Storage.Auth;
    using Microsoft.WindowsAzure.Storage.Table;
    using UnityEngine;
    
  6. Na classe , insira as seguintes variáveis:

        /// <summary>    
        /// allows this class to behave like a singleton
        /// </summary>    
        public static TableToScene instance;
    
        /// <summary>    
        /// Insert here you Azure Storage name     
        /// </summary>    
        private string accountName = " -- Insert your Azure Storage name -- ";
    
        /// <summary>    
        /// Insert here you Azure Storage key    
        /// </summary>    
        private string accountKey = " -- Insert your Azure Storage key -- ";
    

    Nota

    Substitua o valor accountName pelo nome do Serviço de Armazenamento do Azure e pelo valor accountKey pelo valor de chave encontrado no Serviço de Armazenamento do Azure, no Portal do Azure (veja Imagem abaixo).

    obter chave de conta

  7. Agora, adicione os métodos Start() e Awake() para inicializar a classe.

        /// <summary>
        /// Triggers before initialization
        /// </summary>
        void Awake()
        {
            // static instance of this class
            instance = this;
        }
    
        /// <summary>
        /// Use this for initialization
        /// </summary>
        void Start()
        {  
            // Call method to populate the scene with new objects as 
            // pecified in the Azure Table
            PopulateSceneFromTableAsync();
        }
    
  8. Na classe TableToScene , adicione o método que irá obter os valores da Tabela do Azure e utilizá-los para gerar os primitivos adequados na cena.

        /// <summary>    
        /// Populate the scene with new objects as specified in the Azure Table    
        /// </summary>    
        private async void PopulateSceneFromTableAsync()
        {
            // Obtain credentials for the Azure Storage
            StorageCredentials creds = new StorageCredentials(accountName, accountKey);
    
            // Storage account
            CloudStorageAccount account = new CloudStorageAccount(creds, useHttps: true);
    
            // Storage client
            CloudTableClient client = account.CreateCloudTableClient(); 
    
            // Table reference
            CloudTable table = client.GetTableReference("SceneObjectsTable");
    
            TableContinuationToken token = null;
    
            // Query the table for every existing Entity
            do
            {
                // Queries the whole table by breaking it into segments
                // (would happen only if the table had huge number of Entities)
                TableQuerySegment<AzureTableEntity> queryResult = await table.ExecuteQuerySegmentedAsync(new TableQuery<AzureTableEntity>(), token); 
    
                foreach (AzureTableEntity entity in queryResult.Results)
                {
                    GameObject newSceneGameObject = null;
                    Color newColor;
    
                    // check for the Entity Type and spawn in the scene the appropriate Primitive
                    switch (entity.Type)
                    {
                        case "Cube":
                            // Create a Cube in the scene
                            newSceneGameObject = GameObject.CreatePrimitive(PrimitiveType.Cube);
                            newColor = Color.blue;
                            break;
    
                        case "Sphere":
                            // Create a Sphere in the scene
                            newSceneGameObject = GameObject.CreatePrimitive(PrimitiveType.Sphere);
                            newColor = Color.red;
                            break;
    
                        case "Cylinder":
                            // Create a Cylinder in the scene
                            newSceneGameObject = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
                            newColor = Color.yellow;
                            break;
                        default:
                            newColor = Color.white;
                            break;
                    }
    
                    newSceneGameObject.name = entity.RowKey;
    
                    newSceneGameObject.GetComponent<MeshRenderer>().material = new Material(Shader.Find("Diffuse"))
                    {
                        color = newColor
                    };
    
                    //check for the Entity X,Y,Z and move the Primitive at those coordinates
                    newSceneGameObject.transform.position = new Vector3((float)entity.X, (float)entity.Y, (float)entity.Z);
                }
    
                // if the token is null, it means there are no more segments left to query
                token = queryResult.ContinuationToken;
            }
    
            while (token != null);
        }
    
  9. Fora da classe TableToScene , tem de definir a classe utilizada pela aplicação para serializar e anular a serialização das Entidades de Tabela.

        /// <summary>
        /// This objects is used to serialize and deserialize the Azure Table Entity
        /// </summary>
        [System.Serializable]
        public class AzureTableEntity : TableEntity
        {
            public AzureTableEntity(string partitionKey, string rowKey)
                : base(partitionKey, rowKey) { }
    
            public AzureTableEntity() { }
            public string Type { get; set; }
            public double X { get; set; }
            public double Y { get; set; }
            public double Z { get; set; }
        }
    
  10. Certifique-se de que Guarda antes de voltar ao Editor do Unity.

  11. Clique na Câmara Principal a partir do painel Hierarquia para que as respetivas propriedades apareçam no Inspetor.

  12. Com a pasta Scripts aberta, selecione o script TableToScene e arraste-o para a Câmara Principal. O resultado deve ser o seguinte:

    adicionar script à câmara principal

Capítulo 10 - Criar a classe CloudScene no Projeto unity de Ambiente de Trabalho

O segundo script que precisa de criar é o CloudScene, que é responsável por:

  • Registar o evento de clique com o botão esquerdo do rato, para permitir que o utilizador arraste objetos em torno do cenário.

  • Serializar os dados do objeto a partir desta cena do Unity e enviá-lo para a Aplicação de Funções do Azure.

Para criar o segundo script:

  1. Clique com o botão direito do rato dentro da pasta Scripts , clique em Criar, Script C#. Atribua o nome CloudScene ao script

    Captura de ecrã que mostra como criar o novo script mudar o nome do CloudScene

  2. Adicione os seguintes espaços de nomes:

    using Newtonsoft.Json;
    using System.Collections;
    using System.Text;
    using System.Threading.Tasks;
    using UnityEngine;
    using UnityEngine.Networking;
    
  3. Insira as seguintes variáveis:

        /// <summary>
        /// Allows this class to behave like a singleton
        /// </summary>
        public static CloudScene instance;
    
        /// <summary>
        /// Insert here you Azure Function Url
        /// </summary>
        private string azureFunctionEndpoint = "--Insert here you Azure Function Endpoint--";
    
        /// <summary>
        /// Flag for object being moved
        /// </summary>
        private bool gameObjHasMoved;
    
        /// <summary>
        /// Transform of the object being dragged by the mouse
        /// </summary>
        private Transform gameObjHeld;
    
        /// <summary>
        /// Class hosted in the TableToScene script
        /// </summary>
        private AzureTableEntity azureTableEntity;
    
  4. Substitua o valor azureFunctionEndpoint pelo URL da Aplicação de Funções do Azure encontrado no Serviço de Aplicações de Funções do Azure, no Portal do Azure, conforme mostrado na imagem abaixo:

    obter URL da função

  5. Agora, adicione os métodos Start() e Awake() para inicializar a classe.

        /// <summary>
        /// Triggers before initialization
        /// </summary>
        void Awake()
        {
            // static instance of this class
            instance = this;
        }
    
        /// <summary>
        /// Use this for initialization
        /// </summary>
        void Start()
        {
            // initialise an AzureTableEntity
            azureTableEntity = new AzureTableEntity();
        }
    
  6. No método Update(), adicione o seguinte código que irá detetar a entrada e arrastar do rato, o que, por sua vez, irá mover GameObjects na cena. Se o utilizador tiver arrastado e removido um objeto, transmitirá o nome e as coordenadas do objeto ao método UpdateCloudScene(), que irá chamar o serviço Aplicação de Funções do Azure, que irá atualizar a tabela do Azure e acionar a notificação.

        /// <summary>
        /// Update is called once per frame
        /// </summary>
        void Update()
        {
            //Enable Drag if button is held down
            if (Input.GetMouseButton(0))
            {
                // Get the mouse position
                Vector3 mousePosition = new Vector3(Input.mousePosition.x, Input.mousePosition.y, 10);
    
                Vector3 objPos = Camera.main.ScreenToWorldPoint(mousePosition);
    
                Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
    
                RaycastHit hit;
    
                // Raycast from the current mouse position to the object overlapped by the mouse
                if (Physics.Raycast(ray, out hit))
                {
                    // update the position of the object "hit" by the mouse
                    hit.transform.position = objPos;
    
                    gameObjHasMoved = true;
    
                    gameObjHeld = hit.transform;
                }
            }
    
            // check if the left button mouse is released while holding an object
            if (Input.GetMouseButtonUp(0) && gameObjHasMoved)
            {
                gameObjHasMoved = false;
    
                // Call the Azure Function that will update the appropriate Entity in the Azure Table
                // and send a Notification to all subscribed Apps
                Debug.Log("Calling Azure Function");
    
                StartCoroutine(UpdateCloudScene(gameObjHeld.name, gameObjHeld.position.x, gameObjHeld.position.y, gameObjHeld.position.z));
            }
        }
    
  7. Agora, adicione o método UpdateCloudScene(), conforme abaixo:

        private IEnumerator UpdateCloudScene(string objName, double xPos, double yPos, double zPos)
        {
            WWWForm form = new WWWForm();
    
            // set the properties of the AzureTableEntity
            azureTableEntity.RowKey = objName;
    
            azureTableEntity.X = xPos;
    
            azureTableEntity.Y = yPos;
    
            azureTableEntity.Z = zPos;
    
            // Serialize the AzureTableEntity object to be sent to Azure
            string jsonObject = JsonConvert.SerializeObject(azureTableEntity);
    
            using (UnityWebRequest www = UnityWebRequest.Post(azureFunctionEndpoint, jsonObject))
            {
                byte[] jsonToSend = new System.Text.UTF8Encoding().GetBytes(jsonObject);
    
                www.uploadHandler = new UploadHandlerRaw(jsonToSend);
    
                www.uploadHandler.contentType = "application/json";
    
                www.downloadHandler = new DownloadHandlerBuffer();
    
                www.SetRequestHeader("Content-Type", "application/json");
    
                yield return www.SendWebRequest();
    
                string response = www.responseCode.ToString();
            }
        }
    
  8. Guardar o código e regressar ao Unity

  9. Arraste o script CloudScene para a Câmara Principal.

    1. Clique na Câmara Principal a partir do painel Hierarquia para que as respetivas propriedades apareçam no Inspetor.

    2. Com a pasta Scripts aberta, selecione o script CloudScene e arraste-o para a Câmara Principal. O resultado deve ser o seguinte:

      arrastar script de nuvem para a câmara principal

Capítulo 11 - Criar o Projeto de Ambiente de Trabalho para UWP

Tudo o que é necessário para a secção Unity deste projeto foi agora concluído.

  1. Navegue para Definições de Compilação (Definições de Compilação de Ficheiros>).

  2. Na janela Definições de Compilação, clique em Compilar.

    Captura de ecrã que mostra a janela Definições de Compilação com Plataforma Universal do Windows selecionada e o botão

  3. Será apresentada uma janela de Explorador de Ficheiros, solicitando-lhe uma localização para Compilar. Crie uma nova pasta (ao clicar em Nova Pasta no canto superior esquerdo) e dê-lhe o nome BUILDS.

    nova pasta para compilação

    1. Abra a nova pasta BUILDS e crie outra pasta (utilizando Nova Pasta mais uma vez) e dê-lhe o nome NH_Desktop_App.

      nome da pasta NH_Desktop_App

    2. Com a NH_Desktop_App selecionada. clique em Selecionar Pasta. A compilação do projeto demorará cerca de um minuto.

  4. Após a compilação, será apresentada Explorador de Ficheiros a mostrar a localização do seu novo projeto. No entanto, não é necessário abri-lo, pois terá de criar primeiro o outro projeto do Unity, nos próximos Capítulos.

Capítulo 12 - Configurar Mixed Reality Projeto unity

Segue-se uma configuração típica para programar com a realidade mista e, como tal, é um bom modelo para outros projetos.

  1. Abra o Unity e clique em Novo.

    Captura de ecrã que mostra a janela Projetos do Unity com

  2. Agora, terá de fornecer um nome do Projeto do Unity e inserir UnityMRNotifHub. Certifique-se de que o tipo de projeto está definido como 3D. Defina a Localização para um local adequado para si (lembre-se de que é melhor aproximar-se dos diretórios de raiz). Em seguida, clique em Criar projeto.

    name UnityMRNotifHub

  3. Com o Unity aberto, vale a pena verificar se o Editor de Scripts predefinido está definido como Visual Studio. Aceda a Editar>Preferências e, em seguida, a partir da nova janela, navegue para Ferramentas Externas. Altere o Editor de Scripts Externos para o Visual Studio 2017. Feche a janela Preferências .

    definir o editor externo como VS

  4. Em seguida, aceda aDefinições de Compilação de Ficheiros> e mude a plataforma para Plataforma Universal do Windows, clicando no botão Mudar de Plataforma.

    mudar plataformas para UWP

  5. Aceda aDefinições de Compilação de Ficheiros> e certifique-se de que:

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

      Para o Microsoft HoloLens, defina Dispositivo de Destino como HoloLens.

    2. O Tipo de Compilação está definido como D3D

    3. O SDK está definido como Instalado mais recentemente

    4. A Versão do Visual Studio está definida como Mais Recente instalada

    5. A compilação e a execução estão definidas como Máquina Local

    6. Enquanto estiver aqui, vale a pena guardar a cena e adicioná-la à compilação.

      1. Faça-o ao selecionar Adicionar Cenas Abertas. Será apresentada uma janela guardar.

        Captura de ecrã que mostra a janela Definições de Compilação com o botão

      2. Crie uma nova pasta para este cenário e, em seguida, selecione o botão Nova pasta , para criar uma nova pasta, atribua-lhe o nome Cenas.

        Captura de ecrã que mostra

      3. Abra a pasta Cenas recentemente criada e, em seguida, no campo Nome do ficheiro: texto, escreva NH_MR_Scene e, em seguida, prima Guardar.

        nova cena - NH_MR_Scene

    7. As restantes definições, em Definições de Compilação, devem ser deixadas como predefinição por enquanto.

  6. Na mesma janela, clique no botão Definições do Leitor , este procedimento abrirá o painel relacionado no espaço onde o Inspetor está localizado.

    abrir as definições do leitor

  7. Neste painel, é necessário verificar algumas definições:

    1. No separador Outras Definições :

      1. A Versão do Runtime de Scripting deve ser Experimental (.NET 4.6 Equivalente)

      2. O Back-end de Scripts deve ser .NET

      3. O Nível de Compatibilidade da API deve ser .NET 4.6

        compatibilidade com api

    2. Mais abaixo no painel, em Definições XR (encontradas abaixo de Definições de Publicação), marque a Realidade Virtual Suportada, certifique-se de que o SDK Windows Mixed Reality é adicionado

      atualizar definições de xr

    3. No separador Definições de Publicação , em Capacidades, verifique:

      • InternetClient

        Captura de ecrã que mostra o separador Definições de Publicação com InternetClient selecionado.

  8. Novamente em Definições de Compilação, o Unity C# Projects já não está a cinzento: marque a caixa de verificação junto a isto.

  9. Com estas alterações efetuadas, feche a janela Definições de Compilação.

  10. Guarde a Cena e a Cena de Gravação de Ficheiros> do Projeto/Projeto de Gravaçãode Ficheiros>.

    Importante

    Se quiser ignorar o componente Configurar o Unity para este projeto (Aplicação de realidade mista) e continuar diretamente para o código, pode transferir este .unitypackage, importá-lo para o seu projeto como Um Pacote Personalizado e, em seguida, continuar a partir do Capítulo 14. Ainda terá de adicionar os componentes do script.

Capítulo 13 – Importar os DLLs no Projeto do Unity do Mixed Reality

Irá utilizar a biblioteca do Armazenamento do Azure para o Unity (que utiliza o SDK .Net para o Azure). Siga esta ligação sobre como utilizar o Armazenamento do Azure com o Unity. Existe atualmente um problema conhecido no Unity que requer que os plug-ins sejam reconfigurados após a importação. Estes passos (4 a 7 nesta secção) deixarão de ser necessários após a resolução do erro.

Para importar o SDK para o seu próprio projeto, certifique-se de que transferiu o .unitypackage mais recente. Em seguida, faça o seguinte:

  1. Adicione o .unitypackage que transferiu a partir do acima para o Unity com a opção de menu PacotePersonalizadoImportar Pacotes> de Importação de Recursos>.

  2. Na caixa Importar Pacote do Unity que é apresentada, pode selecionar tudo emArmazenamento de Plug-in>.

    importar pacote

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

  4. Aceda à pasta Armazenamento em Plug-ins na vista Projeto e selecione apenas os seguintes plug-ins:

    • Microsoft.Data.Edm
    • Microsoft.Data.OData
    • Microsoft.WindowsAzure.Storage
    • Newtonsoft.Json
    • System.Spatial

    selecionar plug-ins

  5. Com estes plug-ins específicos selecionados,desmarqueQualquer Plataforma e desmarqueWSAPlayer e, em seguida, clique em Aplicar.

    aplicar alterações de plataforma

    Nota

    Está a marcar estes plug-ins específicos para serem utilizados apenas no Editor do Unity. Isto deve-se ao facto de existirem versões diferentes dos mesmos plug-ins na pasta WSA que serão utilizadas depois de o projeto ser exportado do Unity.

  6. Na pasta Plug-in armazenamento , selecione apenas:

    • Microsoft.Data.Services.Client

      selecionar cliente de serviços de dados

  7. Selecione a caixa Não Processar em Definições da Plataforma e clique em Aplicar.

    não processar

    Nota

    Está a marcar este plug-in "Não processe" porque o patcher de assemblagem do Unity tem dificuldade em processar este plug-in. O plug-in continuará a funcionar mesmo que não seja processado.

Capítulo 14 – Criar a classe TableToScene no projeto unity de realidade mista

A classe TableToScene é idêntica à explicada no Capítulo 9. Crie a mesma classe no Projeto unity de realidade mista, seguindo o mesmo procedimento explicado no Capítulo 9.

Depois de concluir este Capítulo, ambos os projetos do Unity terão esta classe configurada na Câmara Principal.

Capítulo 15 - Criar a classe NotificationReceiver no Projeto Mixed Reality Unity

O segundo script que precisa de criar é NotificationReceiver, responsável por:

  • Registar a aplicação no Hub de Notificação na inicialização.
  • Escutar notificações provenientes do Hub de Notificação.
  • Anular a serialização dos dados do objeto a partir de notificações recebidas.
  • Mova os GameObjects na cena, com base nos dados desseriais.

Para criar o script NotificationReceiver :

  1. Clique com o botão direito do rato dentro da pasta Scripts , clique em Criar, C# Script. Atribua o nome NotificationReceiver ao script.

    criar novo nome de script c#notificationReceiver

  2. Faça duplo clique no script para o abrir.

  3. Adicione os seguintes espaços de nomes:

    //using Microsoft.WindowsAzure.Messaging;
    using Newtonsoft.Json;
    using System;
    using System.Collections;
    using UnityEngine;
    
    #if UNITY_WSA_10_0 && !UNITY_EDITOR
    using Windows.Networking.PushNotifications;
    #endif
    
  4. Insira as seguintes variáveis:

        /// <summary>
        /// allows this class to behave like a singleton
        /// </summary>
        public static NotificationReceiver instance;
    
        /// <summary>
        /// Value set by the notification, new object position
        /// </summary>
        Vector3 newObjPosition;
    
        /// <summary>
        /// Value set by the notification, object name
        /// </summary>
        string gameObjectName;
    
        /// <summary>
        /// Value set by the notification, new object position
        /// </summary>
        bool notifReceived;
    
        /// <summary>
        /// Insert here your Notification Hub Service name 
        /// </summary>
        private string hubName = " -- Insert the name of your service -- ";
    
        /// <summary>
        /// Insert here your Notification Hub Service "Listen endpoint"
        /// </summary>
        private string hubListenEndpoint = "-Insert your Notification Hub Service Listen endpoint-";
    
  5. Substitua o valor hubName pelo nome do Serviço do Hub de Notificação e pelo valor hubListenEndpoint pelo valor de ponto final encontrado no separador Políticas de Acesso, Serviço hub de notificação do Azure, no Portal do Azure (veja a imagem abaixo).

    inserir o ponto final da política dos hubs de notificação

  6. Agora, adicione os métodos Iniciar() e Awake() para inicializar a classe.

        /// <summary>
        /// Triggers before initialization
        /// </summary>
        void Awake()
        {
            // static instance of this class
            instance = this;
        }
    
        /// <summary>
        /// Use this for initialization
        /// </summary>
        void Start()
        {
            // Register the App at launch
            InitNotificationsAsync();
    
            // Begin listening for notifications
            StartCoroutine(WaitForNotification());
        }
    
  7. Adicione o método WaitForNotification para permitir que a aplicação receba notificações da Biblioteca do Hub de Notificação sem entrar em conflito com o Thread Principal:

        /// <summary>
        /// This notification listener is necessary to avoid clashes 
        /// between the notification hub and the main thread   
        /// </summary>
        private IEnumerator WaitForNotification()
        {
            while (true)
            {
                // Checks for notifications each second
                yield return new WaitForSeconds(1f);
    
                if (notifReceived)
                {
                    // If a notification is arrived, moved the appropriate object to the new position
                    GameObject.Find(gameObjectName).transform.position = newObjPosition;
    
                    // Reset the flag
                    notifReceived = false;
                }
            }
        }
    
  8. O seguinte método, InitNotificationAsync(), registará a aplicação no Serviço hub de notificação durante a inicialização. O código é comentado, uma vez que o Unity não poderá Criar o projeto. Irá remover os comentários quando importar o pacote Nuget de Mensagens do Azure no Visual Studio.

        /// <summary>
        /// Register this application to the Notification Hub Service
        /// </summary>
        private async void InitNotificationsAsync()
        {
            // PushNotificationChannel channel = await PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync();
    
            // NotificationHub hub = new NotificationHub(hubName, hubListenEndpoint);
    
            // Registration result = await hub.RegisterNativeAsync(channel.Uri);
    
            // If registration was successful, subscribe to Push Notifications
            // if (result.RegistrationId != null)
            // {
            //     Debug.Log($"Registration Successful: {result.RegistrationId}");
            //     channel.PushNotificationReceived += Channel_PushNotificationReceived;
            // }
        }
    
  9. O seguinte processador, Channel_PushNotificationReceived(), será acionado sempre que for recebida uma notificação. Irá anular a anulação da notificação, que será a Entidade de Tabela do Azure que foi movida na Aplicação de Ambiente de Trabalho e, em seguida, moverá o GameObject correspondente na cena do MR para a mesma posição.

    Importante

    O código é comentado porque o código faz referência à biblioteca de Mensagens do Azure, que irá adicionar depois de criar o projeto do Unity com o Gestor de Pacotes Nuget, no Visual Studio. Como tal, o projeto unity não será capaz de criar, a menos que seja comentado. Tenha em atenção que, caso crie o seu projeto e, em seguida, pretenda regressar ao Unity, terá de voltar a comentar esse código.

        ///// <summary>
        ///// Handler called when a Push Notification is received
        ///// </summary>
        //private void Channel_PushNotificationReceived(PushNotificationChannel sender, PushNotificationReceivedEventArgs args)    
        //{
        //    Debug.Log("New Push Notification Received");
        //
        //    if (args.NotificationType == PushNotificationType.Raw)
        //    {
        //        //  Raw content of the Notification
        //        string jsonContent = args.RawNotification.Content;
        //
        //        // Deserialise the Raw content into an AzureTableEntity object
        //        AzureTableEntity ate = JsonConvert.DeserializeObject<AzureTableEntity>(jsonContent);
        //
        //        // The name of the Game Object to be moved
        //        gameObjectName = ate.RowKey;          
        //
        //        // The position where the Game Object has to be moved
        //        newObjPosition = new Vector3((float)ate.X, (float)ate.Y, (float)ate.Z);
        //
        //        // Flag thats a notification has been received
        //        notifReceived = true;
        //    }
        //}
    
  10. Lembre-se de guardar as alterações antes de voltar ao Editor do Unity.

  11. Clique na Câmara Principal a partir do painel Hierarquia para que as respetivas propriedades apareçam no Inspetor.

  12. Com a pasta Scripts aberta, selecione o script NotificationReceiver e arraste-o para a Câmara Principal. O resultado deve ser o seguinte:

    arrastar script do recetor de notificação para a câmara

    Nota

    Se estiver a desenvolver isto para o Microsoft HoloLens, terá de atualizar o componente Câmara principal da Câmara, para que:

    • Limpar Sinalizadores: Cor Sólida
    • Fundo: Preto

Capítulo 16 - Criar o Projeto de Mixed Reality para UWP

Este Capítulo é idêntico ao processo de compilação do projeto anterior. Tudo o que é necessário para a secção Unity deste projeto já foi concluído, por isso está na altura de o construir a partir do Unity.

  1. Navegue para Definições de Compilação (Definições de Compilação de Ficheiros> ).

  2. No menu Definições de Compilação, certifique-se de que o Unity C# Projects* está marcado (o que lhe permitirá editar os scripts neste projeto, após a compilação).

  3. Depois de terminar, clique em Compilar.

    Captura de ecrã que mostra a janela Definições de Compilação com o botão

  4. Será apresentada uma janela de Explorador de Ficheiros, solicitando-lhe uma localização para Compilar. Crie uma nova pasta (ao clicar em Nova Pasta no canto superior esquerdo) e dê-lhe o nome BUILDS.

    criar pasta de compilações

    1. Abra a nova pasta BUILDS e crie outra pasta (utilizando Nova Pasta mais uma vez) e dê-lhe o nome NH_MR_App.

      criar NH_MR_Apps pasta

    2. Com o NH_MR_App selecionado. clique em Selecionar Pasta. A compilação do projeto demorará cerca de um minuto.

  5. Após a compilação, será aberta uma janela de Explorador de Ficheiros na localização do seu novo projeto.

Capítulo 17 - Adicionar pacotes NuGet à Solução UnityMRNotifHub

Aviso

Lembre-se de que, depois de adicionar os seguintes Pacotes NuGet (e anular o comentário do código no capítulo seguinte), o Código, quando reaberto no Projeto do Unity, irá apresentar erros. Se quiser voltar atrás e continuar a editar no Editor do Unity, precisará de comentar esse código errado e, em seguida, anular o comentário novamente mais tarde, assim que voltar ao Visual Studio.

Assim que a compilação da realidade mista estiver concluída, navegue para o projeto de realidade mista, que criou, e faça duplo clique no ficheiro de solução (.sln) nessa pasta, para abrir a sua solução com o Visual Studio 2017. Agora, terá de adicionar o pacote NuGet WindowsAzure.Messaging.managed ; esta é uma biblioteca que é utilizada para receber Notificações do Hub de Notificação.

Para importar o pacote NuGet:

  1. No Explorador de Soluções, clique com o botão direito do rato na solução

  2. Clique em Gerir Pacotes NuGet.

    abrir o gestor nuget

  3. Selecione o separador Procurar e procure WindowsAzure.Messaging.managed.

    localizar o pacote de mensagens do Windows Azure

  4. Selecione o resultado (conforme mostrado abaixo) e, na janela à direita, selecione a caixa de verificação junto a Projeto. Esta ação irá colocar um tique na caixa de verificação junto ao Project, juntamente com a caixa de verificação junto ao projeto Assembly-CSharp e UnityMRNotifHub .

    marcar todos os projetos

  5. A versão fornecida inicialmente pode não ser compatível com este projeto. Por conseguinte, clique no menu pendente junto a Versão e clique em Versão 0.1.7.9 e, em seguida, clique em Instalar.

  6. Acabou de instalar o pacote NuGet. Localize o código comentado que introduziu na classe NotificationReceiver e remova os comentários.

Capítulo 18 - Editar a aplicação UnityMRNotifHub, classe NotificationReceiver

Depois de ter adicionado os Pacotes NuGet, terá de anular o comentário de alguns dos códigos na classe NotificationReceiver .

O que está incluído:

  1. O espaço de nomes na parte superior:

    using Microsoft.WindowsAzure.Messaging;
    
  2. Todo o código no método InitNotificationsAsync():

        /// <summary>
        /// Register this application to the Notification Hub Service
        /// </summary>
        private async void InitNotificationsAsync()
        {
            PushNotificationChannel channel = await PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync();
    
            NotificationHub hub = new NotificationHub(hubName, hubListenEndpoint);
    
            Registration result = await hub.RegisterNativeAsync(channel.Uri);
    
            // If registration was successful, subscribe to Push Notifications
            if (result.RegistrationId != null)
            {
                Debug.Log($"Registration Successful: {result.RegistrationId}");
                channel.PushNotificationReceived += Channel_PushNotificationReceived;
            }
        }
    

Aviso

O código acima tem um comentário: certifique-se de que não descompactou acidentalmente esse comentário (uma vez que o código não será compilado se o tiver feito!).

  1. E, por último, o evento Channel_PushNotificationReceived :

        /// <summary>
        /// Handler called when a Push Notification is received
        /// </summary>
        private void Channel_PushNotificationReceived(PushNotificationChannel sender, PushNotificationReceivedEventArgs args)
        {
            Debug.Log("New Push Notification Received");
    
            if (args.NotificationType == PushNotificationType.Raw)
            {
                //  Raw content of the Notification
                string jsonContent = args.RawNotification.Content;
    
                // Deserialize the Raw content into an AzureTableEntity object
                AzureTableEntity ate = JsonConvert.DeserializeObject<AzureTableEntity>(jsonContent);
    
                // The name of the Game Object to be moved
                gameObjectName = ate.RowKey;
    
                // The position where the Game Object has to be moved
                newObjPosition = new Vector3((float)ate.X, (float)ate.Y, (float)ate.Z);
    
                // Flag thats a notification has been received
                notifReceived = true;
            }
        }
    

Com estes não comentários, certifique-se de que guarda e, em seguida, avance para o capítulo seguinte.

Capítulo 19 – Associar o projeto de realidade mista à aplicação Store

Agora, tem de associar o projeto de realidade mista à Aplicação da Loja em que criou no início do laboratório.

  1. Abra a solução.

  2. Clique com o botão direito do rato no Projeto da aplicação UWP no painel Explorador de Soluções, aceda a Loja e Associe a Aplicação à Loja....

    associação de loja aberta

  3. Será apresentada uma nova janela denominada Associar a Sua Aplicação à Loja Windows. Clique em Seguinte.

    ir para o ecrã seguinte

  4. Carregará todas as Aplicações associadas à Conta em que iniciou sessão. Se não tiver sessão iniciada na sua conta, pode Iniciar Sessão nesta página.

  5. Localize o nome da Aplicação da Loja que criou no início deste tutorial e selecione-o. Em seguida, clique em Seguinte.

    localizar e selecionar o nome da loja

  6. Clique em Associar.

    associar a aplicação

  7. A sua Aplicação está agora Associada à Aplicação da Loja. Isto é necessário para ativar as Notificações.

Capítulo 20 - Implementar aplicações UnityMRNotifHub e UnityDesktopNotifHub

Este Capítulo pode ser mais fácil com duas pessoas, uma vez que o resultado incluirá ambas as aplicações em execução, uma em execução no ambiente de trabalho do computador e outra no headset envolvente.

A aplicação de headset envolvente está à espera de receber alterações à cena (alterações de posição dos GameObjects locais) e a aplicação Ambiente de Trabalho irá efetuar alterações à cena local (alterações de posição), que serão partilhadas com a aplicação MR. Faz sentido implementar primeiro a aplicação MR, seguida pela aplicação Ambiente de Trabalho, para que o recetor possa começar a ouvir.

Para implementar a aplicação UnityMRNotifHub no seu Computador Local:

  1. Abra o ficheiro de solução da sua aplicação UnityMRNotifHub no Visual Studio 2017.

  2. Na Plataforma de Soluções, selecione x86, Máquina Local.

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

    Captura de ecrã que mostra a Configuração da Solução definida como

  4. Aceda ao menu Compilar e clique em Implementar Solução para fazer sideload da aplicação para o seu computador.

  5. A sua Aplicação deverá agora aparecer na lista de aplicações instaladas, prontas para serem iniciadas.

Para implementar a aplicação UnityDesktopNotifHub no Computador Local:

  1. Abra o ficheiro de solução da sua aplicação UnityDesktopNotifHub no Visual Studio 2017.

  2. Na Plataforma de Soluções, selecione x86, Máquina Local.

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

    Captura de ecrã a mostrar a Configuração da Solução definida como

  4. Aceda ao menu Compilar e clique em Implementar Solução para fazer sideload da aplicação para o seu computador.

  5. A sua Aplicação deverá agora aparecer na lista de aplicações instaladas, prontas para serem iniciadas.

  6. Inicie a aplicação de realidade mista, seguida da aplicação Ambiente de Trabalho.

Com ambas as aplicações em execução, mova um objeto na cena do ambiente de trabalho (utilizando o Botão do Rato Esquerdo). Estas alterações posicionais serão efetuadas localmente, serializadas e enviadas para o serviço Aplicação de Funções. Em seguida, o serviço Function App atualizará a Tabela juntamente com o Notification Hub. Depois de receber uma atualização, o Notification Hub enviará os dados atualizados diretamente para todas as aplicações registadas (neste caso, a aplicação de headset envolvente), que irá anular a serialização dos dados recebidos e aplicar os novos dados posicionais aos objetos locais, movendo-os no local.

A sua aplicação dos Hubs de Notificação do Azure terminou

Parabéns, criou uma aplicação de realidade mista que tira partido do Serviço hubs de notificação do Azure e permite a comunicação entre aplicações.

final product -end

Exercícios de bónus

Exercício 1

Pode descobrir como alterar a cor dos GameObjects e enviar essa notificação para outras aplicações que estão a ver a cena?

Exercício 2

Pode adicionar movimento dos GameObjects à sua aplicação MR e ver a cena atualizada na sua aplicação de ambiente de trabalho?