HoloLens (1ère génération) et Azure 305 : Fonctions et stockage
Remarque
Les tutoriels Mixed Reality Academy ont été conçus pour les appareils HoloLens (1re génération) et les casques immersifs de réalité mixte. Nous estimons qu’il est important de laisser ces tutoriels à la disposition des développeurs qui recherchent encore des conseils pour développer des applications sur ces appareils. Notez que ces tutoriels ne sont pas mis à jour avec les derniers ensembles d’outils ou interactions utilisés pour HoloLens 2. Ils sont fournis dans le but de fonctionner sur les appareils pris en charge. Il y aura une nouvelle série de tutoriels qui seront publiés à l’avenir qui montreront comment développer pour HoloLens 2. Cet avis sera mis à jour avec un lien vers ces didacticiels lorsqu’ils sont publiés.
Dans ce cours, vous allez apprendre à créer et utiliser Azure Functions et à stocker des données avec une ressource Stockage Azure, dans une application de réalité mixte.
Azure Functions est un service Microsoft, qui permet aux développeurs d’exécuter de petits morceaux de code, des « fonctions » dans Azure. Cela permet de déléguer le travail au cloud, plutôt que votre application locale, qui peut avoir de nombreux avantages. Azure Functions prend en charge plusieurs langages de développement, notamment C#, F#, Node.js, Java et PHP. Pour plus d’informations, consultez l’article Azure Functions.
Stockage Azure est un service cloud Microsoft, qui permet aux développeurs de stocker des données, avec l’assurance qu’elles seront hautement disponibles, sécurisées, durables, évolutives et redondantes. Cela signifie que Microsoft gère toutes les maintenances et les problèmes critiques pour vous. Pour plus d’informations, consultez l’article Stockage Azure.
Après avoir terminé ce cours, vous aurez une application de casque immersif de réalité mixte qui sera en mesure d’effectuer les opérations suivantes :
- Permettre à l’utilisateur de regarder autour d’une scène.
- Déclenchez la génération d’objets lorsque l’utilisateur regarde un « bouton » 3D.
- Les objets générés seront choisis par une fonction Azure.
- À mesure que chaque objet est généré, l’application stocke le type d’objet dans un fichier Azure, situé dans Stockage Azure.
- Lors du chargement d’une deuxième fois, les données de fichier Azure sont récupérées et utilisées pour relire les actions de génération de l’instance précédente de l’application.
Dans votre application, il vous incombe d’intégrer les résultats à votre conception. Ce cours est conçu pour vous apprendre à intégrer un service Azure à votre projet Unity. Il s’agit de votre travail d’utiliser les connaissances que vous obtenez de ce cours pour améliorer votre application de réalité mixte.
Prise en charge des appareils
Cours | HoloLens | Casques immersifs |
---|---|---|
MR et Azure 305 : Fonctions et stockage | ✔️ | ✔️ |
Remarque
Bien que ce cours se concentre principalement sur les casques immersifs Windows Mixed Reality (VR), vous pouvez également appliquer ce que vous apprenez dans ce cours à Microsoft HoloLens. À mesure que vous suivez le cours, vous verrez des notes sur les modifications que vous devrez peut-être utiliser pour prendre en charge HoloLens.
Prérequis
Remarque
Ce tutoriel est conçu pour les développeurs qui ont une expérience de base avec Unity et C#. Sachez également que les conditions préalables et les instructions écrites contenues dans ce document représentent ce qui a été testé et vérifié au moment de l’écriture (mai 2018). Vous êtes libre d’utiliser le logiciel le plus récent, comme indiqué dans l’article d’installation des outils , bien qu’il ne soit pas supposé que les informations de ce cours correspondent parfaitement à ce que vous trouverez dans les logiciels plus récents que ceux répertoriés ci-dessous.
Nous vous recommandons le matériel et les logiciels suivants pour ce cours :
- Un PC de développement, compatible avec Windows Mixed Reality pour le développement de casque immersif (VR)
- Windows 10 Fall Creators Update (ou version ultérieure) avec le mode développeur activé
- Le sdk Windows 10 le plus récent
- Unity 2017.4
- Visual Studio 2017
- Un casque immersif Windows Mixed Reality (VR) ou Microsoft HoloLens avec le mode développeur activé
- Un abonnement à un compte Azure pour la création de ressources Azure
- Accès Internet pour la configuration et la récupération des données Azure
Avant de commencer
Pour éviter de rencontrer des problèmes lors de la création de ce projet, il est fortement recommandé de créer le projet mentionné dans ce didacticiel dans un dossier racine ou quasi-racine (des chemins de dossier longs peuvent provoquer des problèmes au moment de la génération).
Chapitre 1 - Portail Azure
Pour utiliser le service Stockage Azure, vous devez créer et configurer un compte de stockage dans le Portail Azure.
Connectez-vous au portail Azure.
Remarque
Si vous n’avez pas encore de compte Azure, vous devez en créer un. Si vous suivez ce tutoriel dans une situation de salle de classe ou de laboratoire, demandez à votre instructeur ou à l’un des proctoreurs de vous aider à configurer votre nouveau compte.
Une fois connecté, cliquez sur Nouveau dans le coin supérieur gauche, puis recherchez le compte de stockage, puis cliquez sur Entrée.
Remarque
Le mot Nouveau peut avoir été remplacé par Créer une ressource, dans des portails plus récents.
La nouvelle page fournit une description du service de compte Stockage Azure. En bas à gauche de cette invite, sélectionnez le bouton Créer pour créer une association avec ce service.
Une fois que vous avez cliqué sur Créer :
Insérez un nom pour votre compte, n’oubliez pas que ce champ accepte uniquement les chiffres et les lettres minuscules.
Pour le modèle de déploiement, sélectionnez Resource Manager.
Pour le type de compte, sélectionnez Stockage (usage général v1).
Déterminez l’emplacement de votre groupe de ressources (si vous créez un groupe de ressources). L’emplacement se trouve idéalement dans la région où l’application s’exécute. Certaines ressources Azure sont disponibles uniquement dans certaines régions.
Pour la réplication, sélectionnez Stockage géoredondant avec accès en lecture (RA-GRS).
Pour Performances, sélectionnez Standard.
Laissez le transfert sécurisé requis comme désactivé.
Sélectionnez un Abonnement.
Choisissez un groupe de ressources ou créez-en un. Un groupe de ressources permet de surveiller, de contrôler l’accès, de provisionner et de gérer la facturation d’une collection de ressources Azure. Il est recommandé de conserver tous les services Azure associés à un seul projet (par exemple, ces laboratoires) sous un groupe de ressources commun.
Si vous souhaitez en savoir plus sur les groupes de ressources Azure, consultez l’article du groupe de ressources.
Vous devrez également confirmer que vous avez compris les conditions générales appliquées à ce service.
Sélectionnez Créer.
Une fois que vous avez cliqué sur Créer, vous devrez attendre que le service soit créé, cela peut prendre une minute.
Une notification s’affiche dans le portail une fois l’instance de service créée.
Cliquez sur les notifications pour explorer votre nouvelle instance de service.
Cliquez sur le bouton Accéder à la ressource dans la notification pour explorer votre nouvelle instance de service. Vous êtes redirigé vers votre nouvelle instance de service de compte de stockage.
Cliquez sur Clés d’accès pour afficher les points de terminaison de ce service cloud. Utilisez le Bloc-notes ou similaire pour copier l’une de vos clés pour une utilisation ultérieure. Notez également la valeur de la chaîne de connexion , car elle sera utilisée dans la classe AzureServices , que vous allez créer ultérieurement.
Chapitre 2 - Configuration d’une fonction Azure
Vous allez maintenant écrire une fonction Azure dans le service Azure.
Vous pouvez utiliser une fonction Azure pour effectuer presque tout ce que vous feriez avec une fonction classique dans votre code, la différence étant que cette fonction est accessible par n’importe quelle application disposant d’informations d’identification pour accéder à votre compte Azure.
Pour créer une fonction Azure :
Dans votre portail Azure, cliquez sur Nouveau dans le coin supérieur gauche, puis recherchez l’application de fonction, puis cliquez sur Entrée.
Remarque
Le mot Nouveau peut avoir été remplacé par Créer une ressource, dans des portails plus récents.
La nouvelle page fournit une description du service Azure Function App Service. En bas à gauche de cette invite, sélectionnez le bouton Créer pour créer une association avec ce service.
Une fois que vous avez cliqué sur Créer :
Fournissez un nom d’application. Seules les lettres et les chiffres peuvent être utilisés ici (les majuscules ou minuscules sont autorisées).
Sélectionnez votre abonnement préféré.
Choisissez un groupe de ressources ou créez-en un. Un groupe de ressources permet de surveiller, de contrôler l’accès, de provisionner et de gérer la facturation d’une collection de ressources Azure. Il est recommandé de conserver tous les services Azure associés à un seul projet (par exemple, ces laboratoires) sous un groupe de ressources commun.
Si vous souhaitez en savoir plus sur les groupes de ressources Azure, consultez l’article du groupe de ressources.
Pour cet exercice, sélectionnez Windows comme système d’exploitation choisi.
Sélectionnez Plan de consommation pour le plan d’hébergement.
Déterminez l’emplacement de votre groupe de ressources (si vous créez un groupe de ressources). L’emplacement se trouve idéalement dans la région où l’application s’exécute. Certaines ressources Azure sont disponibles uniquement dans certaines régions. Pour des performances optimales, sélectionnez la même région que le compte de stockage.
Pour le stockage, sélectionnez Utiliser existant, puis utilisez le menu déroulant, recherchez votre stockage créé précédemment.
Laissez Application Insights désactivé pour cet exercice.
Cliquez sur le bouton Créer.
Une fois que vous avez cliqué sur Créer, vous devrez attendre que le service soit créé, cela peut prendre une minute.
Une notification s’affiche dans le portail une fois l’instance de service créée.
Cliquez sur les notifications pour explorer votre nouvelle instance de service.
Cliquez sur le bouton Accéder à la ressource dans la notification pour explorer votre nouvelle instance de service. Vous êtes redirigé vers votre nouvelle instance Function App Service.
Dans le tableau de bord de l’application de fonction, placez votre souris sur Functions, située dans le panneau situé à gauche, puis cliquez sur le symbole + (plus).
Dans la page suivante, vérifiez que Webhook + API est sélectionné et, pour choisir une langue, sélectionnez CSharp, car il s’agit du langage utilisé pour ce didacticiel. Enfin, cliquez sur le bouton Créer cette fonction .
Vous devez être dirigé vers la page de codes (run.csx), si ce n’est pas le cas, cliquez sur la fonction nouvellement créée dans la liste Fonctions dans le panneau situé à gauche.
Copiez le code suivant dans votre fonction. Cette fonction retourne simplement un entier aléatoire compris entre 0 et 2 lorsqu’elle est appelée. Ne vous inquiétez pas du code existant, n’hésitez pas à coller sur le dessus de celui-ci.
using System.Net; using System.Threading.Tasks; public static int Run(CustomObject req, TraceWriter log) { Random rnd = new Random(); int randomInt = rnd.Next(0, 3); return randomInt; } public class CustomObject { public String name {get; set;} }
Cliquez sur Enregistrer.
Le résultat doit ressembler à l’image ci-dessous.
Cliquez sur Obtenir l’URL de la fonction et notez le point de terminaison affiché. Vous devrez l’insérer dans la classe AzureServices que vous allez créer plus loin dans ce cours.
Chapitre 3 - Configuration du projet Unity
Voici une configuration classique pour le développement avec la réalité mixte et, par conséquent, un bon modèle pour d’autres projets.
Configurez et testez votre casque immersif de réalité mixte.
Remarque
Vous n’aurez pas besoin des contrôleurs de mouvement pour ce cours. Si vous avez besoin de support pour configurer le casque immersif, consultez l’article de configuration de réalité mixte.
Ouvrez Unity, puis cliquez sur Nouveau.
Vous devez maintenant fournir un nom de projet Unity. Insérez MR_Azure_Functions. Vérifiez que le type de projet est défini sur 3D. Définissez l’emplacement sur un emplacement approprié pour vous (n’oubliez pas que les répertoires racines sont plus proches). Cliquez ensuite sur Créer un projet.
Avec Unity ouvert, il vaut la peine de vérifier que l’éditeur de script par défaut est défini sur Visual Studio. Accédez à Modifier>les préférences, puis à partir de la nouvelle fenêtre, accédez à Outils externes. Remplacez l’éditeur de script externe par Visual Studio 2017. Fermez la fenêtre Préférences.
Ensuite, accédez aux >paramètres de génération de fichiers et basculez la plateforme vers plateforme Windows universelle, en cliquant sur le bouton Basculer la plateforme.
Accédez aux paramètres de génération de fichiers>et assurez-vous que :
L’appareil cible est défini sur n’importe quel appareil.
Pour Microsoft HoloLens, définissez l’appareil cible sur HoloLens.
Le type de build est défini sur D3D
Le KIT SDK est défini sur La dernière version installée
La version de Visual Studio est définie sur La dernière version installée
La génération et l’exécution sont définies sur Ordinateur local
Enregistrez la scène et ajoutez-la à la build.
Pour ce faire, sélectionnez Ajouter des scènes ouvertes. Une fenêtre d’enregistrement s’affiche.
Créez un dossier pour cela et toute scène future, puis sélectionnez le bouton Nouveau dossier pour créer un dossier, nommez-le Scènes.
Ouvrez votre dossier Scènes nouvellement créé, puis dans le champ Fichier : champ de texte, tapez FunctionsScene, puis appuyez sur Enregistrer.
Les paramètres restants, dans Paramètres de build, doivent être laissés comme valeurs par défaut pour l’instant.
Dans la fenêtre Paramètres de build, cliquez sur le bouton Paramètres du lecteur, ce qui ouvre le panneau associé dans l’espace où se trouve l’inspecteur.
Dans ce panneau, quelques paramètres doivent être vérifiés :
Sous l’onglet Autres paramètres :
- La version du runtime de script doit être expérimentale (équivalent .NET 4.6), ce qui déclenche un redémarrage de l’éditeur.
- Le serveur principal de script doit être .NET
- Le niveau de compatibilité des API doit être .NET 4.6
Sous l’onglet Paramètres de publication, sous Fonctionnalités, vérifiez :
InternetClient
Plus loin dans le panneau, dans les paramètres XR (trouvés ci-dessous paramètres de publication), cochez Virtual Reality Pris en charge, vérifiez que le Kit de développement logiciel (SDK ) Windows Mixed Reality est ajouté.
De retour dans les projets Unity C# des paramètres de build n’est plus grisé ; cochez la case en regard de cela.
Fermez la fenêtre Build Settings.
Enregistrez votre scène et votre projet (FILE>SAVE SCENE / FILE>SAVE PROJECT).
Chapitre 4 - Configurer la caméra principale
Important
Si vous souhaitez ignorer les composants de configuration Unity de ce cours et continuer directement dans le code, n’hésitez pas à télécharger ce .unitypackage et à l’importer dans votre projet en tant que package personnalisé. Cela contiendra également les DLL du chapitre suivant. Après l’importation, continuez à partir du chapitre 7.
Dans le panneau Hierarchy, vous trouverez un objet appelé Main Camera, cet objet représente votre point de vue « tête » une fois que vous êtes « à l’intérieur » de votre application.
Avec le tableau de bord Unity devant vous, sélectionnez l’objet Main Camera GameObject. Vous remarquerez que le panneau Inspecteur (généralement trouvé à droite, dans le tableau de bord) affiche les différents composants de ce GameObject, avec Transform en haut, suivi de Caméra et d’autres composants. Vous devrez réinitialiser la transformation de la caméra principale, de sorte qu’elle est positionnée correctement.
Pour ce faire, sélectionnez l’icône Engrenage en regard du composant Transformation de l’appareil photo, puis sélectionnez Réinitialiser.
Ensuite, mettez à jour le composant Transform pour qu’il ressemble à ceci :
Transformation - Position
X | Y | Z |
---|---|---|
0 | 1 | 0 |
Transformation - Rotation
X | Y | Z |
---|---|---|
0 | 0 | 0 |
Transformation - Mise à l’échelle
X | Y | Z |
---|---|---|
1 | 1 | 1 |
Chapitre 5 - Configuration de la scène Unity
Cliquez avec le bouton droit dans une zone vide du panneau Hiérarchie, sous Objet 3D, ajoutez un plan.
Une fois l’objet Plane sélectionné, modifiez les paramètres suivants dans le panneau Inspecteur :
Transformation - Position
X | Y | Z |
---|---|---|
0 | 0 | 4 |
Transformation - Mise à l’échelle
X | Y | Z |
---|---|---|
10 | 1 | 10 |
Cliquez avec le bouton droit dans une zone vide du panneau Hiérarchie, sous Objet 3D, ajoutez un cube.
Renommez le cube en gazeButton (avec le cube sélectionné, appuyez sur « F2 »).
Modifiez les paramètres suivants pour la position de transformation dans le panneau Inspecteur :
X Y Z 0 3 5 Cliquez sur le bouton déroulant Balise , puis cliquez sur Ajouter une balise pour ouvrir le volet Étiquettes et couches.
Sélectionnez le bouton + (plus), puis, dans le champ Nouveau nom de balise, entrez GazeButton, puis appuyez sur Enregistrer.
Cliquez sur l’objet GazeButton dans le panneau De hiérarchie, puis dans le panneau Inspecteur, affectez la balise GazeButton nouvellement créée.
Cliquez avec le bouton droit sur l’objet GazeButton , dans le panneau Hierarchy, puis ajoutez un GameObject vide (qui sera ajouté en tant qu’objet enfant ).
Sélectionnez le nouvel objet et renommez-le ShapeSpawnPoint.
Modifiez les paramètres suivants pour la position de transformation dans le panneau Inspecteur :
X Y Z 0 -1 0
Ensuite, vous allez créer un objet texte 3D pour fournir des commentaires sur l’état du service Azure.
Cliquez avec le bouton droit sur le gazeButton dans le panneau hiérarchie et ajoutez un objet texte 3D d’objet 3D> en tant qu’enfant.
Renommez l’objet Texte 3D en AzureStatusText.
Modifiez la position de transformation de l’objet AzureStatusText comme suit :
X Y Z 0 0 -0.6 Modifiez l’échelle de transformation de l’objet AzureStatusText comme suit : | X | Y | Z | | :--- : | :--- : | :--- : | | | 0.1 | 0.1 | 0.1 | 0.1 |
Remarque
Ne vous inquiétez pas s’il semble être hors centre, car cela sera résolu lorsque le composant Text Mesh ci-dessous est mis à jour.
Modifiez le composant Text Mesh pour qu’il corresponde à ce qui suit :
Conseil
La couleur sélectionnée ici est hex color : 000000FF, bien que n’hésitez pas à choisir votre propre, assurez-vous qu’il est lisible.
Votre structure du panneau de hiérarchie doit maintenant ressembler à ceci :
Votre scène doit maintenant ressembler à ceci :
Chapitre 6 - Importer Stockage Azure pour Unity
Vous utiliserez Stockage Azure pour Unity (qui tire lui-même parti du Kit de développement logiciel (SDK) .Net pour Azure). Pour en savoir plus, consultez l’article Stockage Azure pour Unity.
Il existe actuellement un problème connu dans Unity qui nécessite la reconfiguration des plug-ins après l’importation. Ces étapes (4 à 7 dans cette section) ne seront plus nécessaires une fois le bogue résolu.
Pour importer le Kit de développement logiciel (SDK) dans votre propre projet, vérifiez que vous avez téléchargé la dernière version de « .unitypackage » à partir de GitHub. Ensuite, procédez comme suit :
Ajoutez le fichier .unitypackage à Unity à l’aide de l’option de menu Package personnalisé De package> d’importation de ressources.>
Dans la zone Importer un package Unity qui s’affiche, vous pouvez sélectionner tout sous Stockage de plug-ins>. Décochez tout le reste, car il n’est pas nécessaire pour ce cours.
Cliquez sur le bouton Importer pour ajouter les éléments à votre projet.
Accédez au dossier Stockage sous Plug-ins, dans l’affichage Projet, puis sélectionnez les plug-ins suivants uniquement :
Microsoft.Data.Edm
Microsoft.Data.OData
Microsoft.WindowsAzure.Storage
Newtonsoft.Json
System.Spatial
Avec ces plug-ins spécifiques sélectionnés, décochez n’importe quelle plateforme et décochez WSAPlayer, puis cliquez sur Appliquer.
Remarque
Nous marquageons ces plug-ins particuliers à utiliser uniquement dans l’éditeur Unity. Cela est dû au fait qu’il existe différentes versions des mêmes plug-ins dans le dossier WSA qui seront utilisés après l’exportation du projet à partir d’Unity.
Dans le dossier du plug-in de stockage , sélectionnez uniquement :
Microsoft.Data.Services.Client
Cochez la case Ne pas traiter sous Paramètres de la plateforme, puis cliquez sur Appliquer.
Remarque
Nous marquageons ce plug-in « Ne pas traiter », car le correctif d’assembly Unity a des difficultés à traiter ce plug-in. Le plug-in fonctionne toujours même s’il n’est pas traité.
Chapitre 7 - Créer la classe AzureServices
La première classe que vous allez créer est la classe AzureServices .
La classe AzureServices est responsable des opérations suivantes :
Stockage des informations d’identification du compte Azure.
Appel de votre fonction Azure App.
Chargement et téléchargement du fichier de données dans votre Stockage Cloud Azure.
Pour créer cette classe :
Cliquez avec le bouton droit dans le dossier de ressources, situé dans le volet projet, créez>un dossier. Nommez le dossier Scripts.
Double-cliquez sur le dossier créé, pour l’ouvrir.
Cliquez avec le bouton droit dans le dossier, créez>un script C#. Appelez le script AzureServices.
Double-cliquez sur la nouvelle classe AzureServices pour l’ouvrir avec Visual Studio.
Ajoutez les espaces de noms suivants en haut d’AzureServices :
using System; using System.Threading.Tasks; using UnityEngine; using Microsoft.WindowsAzure.Storage; using Microsoft.WindowsAzure.Storage.File; using System.IO; using System.Net;
Ajoutez les champs d’inspecteur suivants à l’intérieur de la classe AzureServices :
/// <summary> /// Provides Singleton-like behavior to this class. /// </summary> public static AzureServices instance; /// <summary> /// Reference Target for AzureStatusText Text Mesh object /// </summary> public TextMesh azureStatusText;
Ajoutez ensuite les variables membres suivantes à l’intérieur de la classe AzureServices :
/// <summary> /// Holds the Azure Function endpoint - Insert your Azure Function /// Connection String here. /// </summary> private readonly string azureFunctionEndpoint = "--Insert here you AzureFunction Endpoint--"; /// <summary> /// Holds the Storage Connection String - Insert your Azure Storage /// Connection String here. /// </summary> private readonly string storageConnectionString = "--Insert here you AzureStorage Connection String--"; /// <summary> /// Name of the Cloud Share - Hosts directories. /// </summary> private const string fileShare = "fileshare"; /// <summary> /// Name of a Directory within the Share /// </summary> private const string storageDirectory = "storagedirectory"; /// <summary> /// The Cloud File /// </summary> private CloudFile shapeIndexCloudFile; /// <summary> /// The Linked Storage Account /// </summary> private CloudStorageAccount storageAccount; /// <summary> /// The Cloud Client /// </summary> private CloudFileClient fileClient; /// <summary> /// The Cloud Share - Hosts Directories /// </summary> private CloudFileShare share; /// <summary> /// The Directory in the share that will host the Cloud file /// </summary> private CloudFileDirectory dir;
Important
Veillez à remplacer le point de terminaison et chaîne de connexion valeurs par les valeurs de votre stockage Azure, trouvées dans le portail Azure
Les méthodes Code for Awake() et Start() doivent maintenant être ajoutées. Ces méthodes sont appelées lorsque la classe initialise :
private void Awake() { instance = this; } // Use this for initialization private void Start() { // Set the Status text to loading, whilst attempting connection to Azure. azureStatusText.text = "Loading..."; } /// <summary> /// Call to the Azure Function App to request a Shape. /// </summary> public async void CallAzureFunctionForNextShape() { }
Important
Nous allons renseigner le code de CallAzureFunctionForNextShape() dans un prochain chapitre.
Supprimez la méthode Update(), car cette classe ne l’utilisera pas.
Enregistrez vos modifications dans Visual Studio, puis revenez à Unity.
Cliquez et faites glisser la classe AzureServices du dossier Scripts vers l’objet Caméra principale dans le panneau Hierarchy.
Sélectionnez la caméra principale, puis récupérez l’objet enfant AzureStatusText sous l’objet GazeButton, puis placez-le dans le champ cible de référence AzureStatusText, dans l’Inspecteur, pour fournir la référence au script AzureServices.
Chapitre 8 - Créer la classe ShapeFactory
Le script suivant à créer est la classe ShapeFactory . Le rôle de cette classe consiste à créer une nouvelle forme, quand elle est demandée et à conserver un historique des formes créées dans une liste d’historique des formes. Chaque fois qu’une forme est créée, la liste Historique des formes est mise à jour dans la classe AzureService, puis stockée dans votre Stockage Azure. Au démarrage de l’application, si un fichier stocké se trouve dans votre Stockage Azure, la liste historique des formes est récupérée et relue, avec l’objet Texte 3D qui indique si la forme générée provient du stockage ou de la nouvelle.
Pour créer cette classe :
Accédez au dossier Scripts que vous avez créé précédemment.
Cliquez avec le bouton droit dans le dossier, créez>un script C#. Appelez le script ShapeFactory.
Double-cliquez sur le nouveau script ShapeFactory pour l’ouvrir avec Visual Studio.
Vérifiez que la classe ShapeFactory inclut les espaces de noms suivants :
using System.Collections.Generic; using UnityEngine;
Ajoutez les variables ci-dessous à la classe ShapeFactory , puis remplacez les fonctions Start() et Awake() par celles ci-dessous :
/// <summary> /// Provide this class Singleton-like behaviour /// </summary> [HideInInspector] public static ShapeFactory instance; /// <summary> /// Provides an Inspector exposed reference to ShapeSpawnPoint /// </summary> [SerializeField] public Transform spawnPoint; /// <summary> /// Shape History Index /// </summary> [HideInInspector] public List<int> shapeHistoryList; /// <summary> /// Shapes Enum for selecting required shape /// </summary> private enum Shapes { Cube, Sphere, Cylinder } private void Awake() { instance = this; } private void Start() { shapeHistoryList = new List<int>(); }
La méthode CreateShape() génère les formes primitives, en fonction du paramètre entier fourni. Le paramètre booléen est utilisé pour spécifier si la forme actuellement créée provient du stockage ou du nouveau. Placez le code suivant dans votre classe ShapeFactory , sous les méthodes précédentes :
/// <summary> /// Use the Shape Enum to spawn a new Primitive object in the scene /// </summary> /// <param name="shape">Enumerator Number for Shape</param> /// <param name="storageShape">Provides whether this is new or old</param> internal void CreateShape(int shape, bool storageSpace) { Shapes primitive = (Shapes)shape; GameObject newObject = null; string shapeText = storageSpace == true ? "Storage: " : "New: "; AzureServices.instance.azureStatusText.text = string.Format("{0}{1}", shapeText, primitive.ToString()); switch (primitive) { case Shapes.Cube: newObject = GameObject.CreatePrimitive(PrimitiveType.Cube); break; case Shapes.Sphere: newObject = GameObject.CreatePrimitive(PrimitiveType.Sphere); break; case Shapes.Cylinder: newObject = GameObject.CreatePrimitive(PrimitiveType.Cylinder); break; } if (newObject != null) { newObject.transform.position = spawnPoint.position; newObject.transform.localScale = new Vector3(0.5f, 0.5f, 0.5f); newObject.AddComponent<Rigidbody>().useGravity = true; newObject.GetComponent<Renderer>().material.color = UnityEngine.Random.ColorHSV(0f, 1f, 1f, 1f, 0.5f, 1f); } }
Veillez à enregistrer vos modifications dans Visual Studio avant de revenir à Unity.
De retour dans l’Éditeur Unity, cliquez et faites glisser la classe ShapeFactory du dossier Scripts vers l’objet Appareil photo principal dans le panneau Hiérarchie.
Avec la caméra principale sélectionnée, vous remarquerez que le composant de script ShapeFactory est manquant dans la référence du point de génération. Pour le corriger, faites glisser l’objet ShapeSpawnPoint du panneau Hierarchy vers la cible de référence du point de génération.
Chapitre 9 - Créer la classe De regard
Le dernier script que vous devez créer est la classe Regarde .
Cette classe est chargée de créer un Raycast qui sera projeté à partir de la caméra principale pour détecter l’objet que l’utilisateur examine. Dans ce cas, raycast doit identifier si l’utilisateur examine l’objet GazeButton dans la scène et déclenche un comportement.
Pour créer cette classe :
Accédez au dossier Scripts que vous avez créé précédemment.
Cliquez avec le bouton droit dans le volet projet, créez>un script C#. Appelez le regard du script.
Double-cliquez sur le nouveau script De regard pour l’ouvrir avec Visual Studio.
Vérifiez que l’espace de noms suivant est inclus en haut du script :
using UnityEngine;
Ajoutez ensuite les variables suivantes à l’intérieur de la classe De regard :
/// <summary> /// Provides Singleton-like behavior to this class. /// </summary> public static Gaze instance; /// <summary> /// The Tag which the Gaze will use to interact with objects. Can also be set in editor. /// </summary> public string InteractibleTag = "GazeButton"; /// <summary> /// The layer which will be detected by the Gaze ('~0' equals everything). /// </summary> public LayerMask LayerMask = ~0; /// <summary> /// The Max Distance the gaze should travel, if it has not hit anything. /// </summary> public float GazeMaxDistance = 300; /// <summary> /// The size of the cursor, which will be created. /// </summary> public Vector3 CursorSize = new Vector3(0.05f, 0.05f, 0.05f); /// <summary> /// The color of the cursor - can be set in editor. /// </summary> public Color CursorColour = Color.HSVToRGB(0.0223f, 0.7922f, 1.000f); /// <summary> /// Provides when the gaze is ready to start working (based upon whether /// Azure connects successfully). /// </summary> internal bool GazeEnabled = false; /// <summary> /// The currently focused object. /// </summary> internal GameObject FocusedObject { get; private set; } /// <summary> /// The object which was last focused on. /// </summary> internal GameObject _oldFocusedObject { get; private set; } /// <summary> /// The info taken from the last hit. /// </summary> internal RaycastHit HitInfo { get; private set; } /// <summary> /// The cursor object. /// </summary> internal GameObject Cursor { get; private set; } /// <summary> /// Provides whether the raycast has hit something. /// </summary> internal bool Hit { get; private set; } /// <summary> /// This will store the position which the ray last hit. /// </summary> internal Vector3 Position { get; private set; } /// <summary> /// This will store the normal, of the ray from its last hit. /// </summary> internal Vector3 Normal { get; private set; } /// <summary> /// The start point of the gaze ray cast. /// </summary> private Vector3 _gazeOrigin; /// <summary> /// The direction in which the gaze should be. /// </summary> private Vector3 _gazeDirection;
Important
Certaines de ces variables peuvent être modifiées dans l’éditeur.
Le code des méthodes Awake() et Start() doit maintenant être ajouté.
/// <summary> /// The method used after initialization of the scene, though before Start(). /// </summary> private void Awake() { // Set this class to behave similar to singleton instance = this; } /// <summary> /// Start method used upon initialization. /// </summary> private void Start() { FocusedObject = null; Cursor = CreateCursor(); }
Ajoutez le code suivant, qui crée un objet de curseur au début, ainsi que la méthode Update(), qui exécute la méthode Raycast, ainsi que l’emplacement où le booléen gazeEnabled est activé :
/// <summary> /// Method to create a cursor object. /// </summary> /// <returns></returns> private GameObject CreateCursor() { GameObject newCursor = GameObject.CreatePrimitive(PrimitiveType.Sphere); newCursor.SetActive(false); // Remove the collider, so it doesn't block raycast. Destroy(newCursor.GetComponent<SphereCollider>()); newCursor.transform.localScale = CursorSize; newCursor.GetComponent<MeshRenderer>().material = new Material(Shader.Find("Diffuse")) { color = CursorColour }; newCursor.name = "Cursor"; newCursor.SetActive(true); return newCursor; } /// <summary> /// Called every frame /// </summary> private void Update() { if(GazeEnabled == true) { _gazeOrigin = Camera.main.transform.position; _gazeDirection = Camera.main.transform.forward; UpdateRaycast(); } }
Ajoutez ensuite la méthode UpdateRaycast(), qui projetera une raycast et détectera la cible atteinte.
private void UpdateRaycast() { // Set the old focused gameobject. _oldFocusedObject = FocusedObject; RaycastHit hitInfo; // Initialise Raycasting. Hit = Physics.Raycast(_gazeOrigin, _gazeDirection, out hitInfo, GazeMaxDistance, LayerMask); HitInfo = hitInfo; // Check whether raycast has hit. if (Hit == true) { Position = hitInfo.point; Normal = hitInfo.normal; // Check whether the hit has a collider. if (hitInfo.collider != null) { // Set the focused object with what the user just looked at. FocusedObject = hitInfo.collider.gameObject; } else { // Object looked on is not valid, set focused gameobject to null. FocusedObject = null; } } else { // No object looked upon, set focused gameobject to null. FocusedObject = null; // Provide default position for cursor. Position = _gazeOrigin + (_gazeDirection * GazeMaxDistance); // Provide a default normal. Normal = _gazeDirection; } // Lerp the cursor to the given position, which helps to stabilize the gaze. Cursor.transform.position = Vector3.Lerp(Cursor.transform.position, Position, 0.6f); // Check whether the previous focused object is this same // object. If so, reset the focused object. if (FocusedObject != _oldFocusedObject) { ResetFocusedObject(); if (FocusedObject != null) { if (FocusedObject.CompareTag(InteractibleTag.ToString())) { // Set the Focused object to green - success! FocusedObject.GetComponent<Renderer>().material.color = Color.green; // Start the Azure Function, to provide the next shape! AzureServices.instance.CallAzureFunctionForNextShape(); } } } }
Enfin, ajoutez la méthode ResetFocusedObject(), qui bascule la couleur actuelle des objets GazeButton, indiquant s’il crée une forme ou non.
/// <summary> /// Reset the old focused object, stop the gaze timer, and send data if it /// is greater than one. /// </summary> private void ResetFocusedObject() { // Ensure the old focused object is not null. if (_oldFocusedObject != null) { if (_oldFocusedObject.CompareTag(InteractibleTag.ToString())) { // Set the old focused object to red - its original state. _oldFocusedObject.GetComponent<Renderer>().material.color = Color.red; } } }
Enregistrez vos modifications dans Visual Studio avant de revenir à Unity.
Cliquez et faites glisser la classe De regard du dossier Scripts vers l’objet Caméra principale dans le panneau Hiérarchie.
Chapitre 10 - Fin de la classe AzureServices
Avec les autres scripts en place, il est désormais possible de terminer la classe AzureServices . Pour ce faire, procédez comme suit :
Ajout d’une nouvelle méthode nommée CreateCloudIdentityAsync() pour configurer les variables d’authentification nécessaires pour communiquer avec Azure.
Cette méthode vérifie également l’existence d’un fichier précédemment stocké contenant la liste de formes.
Si le fichier est trouvé, il désactive le regard de l’utilisateur et déclenche la création de la forme, en fonction du modèle de formes, tel qu’il est stocké dans le fichier Stockage Azure. L’utilisateur peut le voir, car le maillage de texte fournit l’affichage « Stockage » ou « Nouveau », en fonction de l’origine des formes.
Si aucun fichier n’est trouvé, il active le regard, ce qui permet à l’utilisateur de créer des formes lors de la recherche de l’objet GazeButton dans la scène.
/// <summary> /// Create the references necessary to log into Azure /// </summary> private async void CreateCloudIdentityAsync() { // Retrieve storage account information from connection string storageAccount = CloudStorageAccount.Parse(storageConnectionString); // Create a file client for interacting with the file service. fileClient = storageAccount.CreateCloudFileClient(); // Create a share for organizing files and directories within the storage account. share = fileClient.GetShareReference(fileShare); await share.CreateIfNotExistsAsync(); // Get a reference to the root directory of the share. CloudFileDirectory root = share.GetRootDirectoryReference(); // Create a directory under the root directory dir = root.GetDirectoryReference(storageDirectory); await dir.CreateIfNotExistsAsync(); //Check if the there is a stored text file containing the list shapeIndexCloudFile = dir.GetFileReference("TextShapeFile"); if (!await shapeIndexCloudFile.ExistsAsync()) { // File not found, enable gaze for shapes creation Gaze.instance.GazeEnabled = true; azureStatusText.text = "No Shape\nFile!"; } else { // The file has been found, disable gaze and get the list from the file Gaze.instance.GazeEnabled = false; azureStatusText.text = "Shape File\nFound!"; await ReplicateListFromAzureAsync(); } }
L’extrait de code suivant provient de la méthode Start() ; où un appel est effectué vers la méthode CreateCloudIdentityAsync(). N’hésitez pas à copier sur votre méthode Start() actuelle, avec les éléments suivants :
private void Start() { // Disable TLS cert checks only while in Unity Editor (until Unity adds support for TLS) #if UNITY_EDITOR ServicePointManager.ServerCertificateValidationCallback = delegate { return true; }; #endif // Set the Status text to loading, whilst attempting connection to Azure. azureStatusText.text = "Loading..."; //Creating the references necessary to log into Azure and check if the Storage Directory is empty CreateCloudIdentityAsync(); }
Renseignez le code de la méthode CallAzureFunctionForNextShape(). Vous allez utiliser l’application de fonction Azure créée précédemment pour demander un index de forme. Une fois la nouvelle forme reçue, cette méthode envoie la forme à la classe ShapeFactory pour créer la nouvelle forme dans la scène. Utilisez le code ci-dessous pour terminer le corps de CallAzureFunctionForNextShape().
/// <summary> /// Call to the Azure Function App to request a Shape. /// </summary> public async void CallAzureFunctionForNextShape() { int azureRandomInt = 0; // Call Azure function HttpWebRequest webRequest = WebRequest.CreateHttp(azureFunctionEndpoint); WebResponse response = await webRequest.GetResponseAsync(); // Read response as string using (Stream stream = response.GetResponseStream()) { StreamReader reader = new StreamReader(stream); String responseString = reader.ReadToEnd(); //parse result as integer Int32.TryParse(responseString, out azureRandomInt); } //add random int from Azure to the ShapeIndexList ShapeFactory.instance.shapeHistoryList.Add(azureRandomInt); ShapeFactory.instance.CreateShape(azureRandomInt, false); //Save to Azure storage await UploadListToAzureAsync(); }
Ajoutez une méthode pour créer une chaîne, en concaténant les entiers stockés dans la liste de l’historique des formes et en l’enregistrant dans votre fichier Stockage Azure.
/// <summary> /// Upload the locally stored List to Azure /// </summary> private async Task UploadListToAzureAsync() { // Uploading a local file to the directory created above string listToString = string.Join(",", ShapeFactory.instance.shapeHistoryList.ToArray()); await shapeIndexCloudFile.UploadTextAsync(listToString); }
Ajoutez une méthode pour récupérer le texte stocké dans le fichier situé dans votre fichier Stockage Azure et le désérialiser dans une liste.
Une fois ce processus terminé, la méthode réactive le regard afin que l’utilisateur puisse ajouter d’autres formes à la scène.
///<summary> /// Get the List stored in Azure and use the data retrieved to replicate /// a Shape creation pattern ///</summary> private async Task ReplicateListFromAzureAsync() { string azureTextFileContent = await shapeIndexCloudFile.DownloadTextAsync(); string[] shapes = azureTextFileContent.Split(new char[] { ',' }); foreach (string shape in shapes) { int i; Int32.TryParse(shape.ToString(), out i); ShapeFactory.instance.shapeHistoryList.Add(i); ShapeFactory.instance.CreateShape(i, true); await Task.Delay(500); } Gaze.instance.GazeEnabled = true; azureStatusText.text = "Load Complete!"; }
Enregistrez vos modifications dans Visual Studio avant de revenir à Unity.
Chapitre 11 - Générer la solution UWP
Pour commencer le processus de génération :
Accédez aux paramètres de génération de fichier>.
Cliquez sur Générer. Unity lance une fenêtre Explorateur de fichiers, où vous devez créer, puis sélectionner un dossier dans lequel générer l’application. Créez maintenant ce dossier et nommez-le App. Ensuite, avec le dossier d’application sélectionné, appuyez sur Sélectionner un dossier.
Unity commence à générer votre projet dans le dossier Application .
Une fois que Unity a terminé la génération (cela peut prendre un certain temps), il ouvre une fenêtre de Explorateur de fichiers à l’emplacement de votre build (vérifiez votre barre des tâches, car elle peut ne pas toujours apparaître au-dessus de vos fenêtres, mais vous informera de l’ajout d’une nouvelle fenêtre).
Chapitre 12 - Déploiement de votre application
Pour déployer votre application :
Accédez au dossier Application qui a été créé dans le dernier chapitre. Vous verrez un fichier portant le nom de vos applications, avec l’extension « .sln », que vous devez double-cliquer pour l’ouvrir dans Visual Studio.
Dans la plateforme de solutions, sélectionnez x86, Ordinateur local.
Dans la configuration de la solution, sélectionnez Déboguer.
Pour Microsoft HoloLens, vous trouverez peut-être plus facile de définir ce paramètre sur l’ordinateur distant afin que vous ne soyez pas attaché à votre ordinateur. Toutefois, vous devez également effectuer les opérations suivantes :
- Connaissez l’adresse IP de votre HoloLens, qui se trouve dans les> options avancées paramètres réseau et Wi-Fi>Internet>; L’adresse IPv4 est l’adresse que vous devez utiliser.
- Vérifiez que le mode développeur est activé ; trouvé dans La mise à jour des paramètres>et la sécurité>pour les développeurs.
Accédez au menu Générer , puis cliquez sur Déployer la solution pour charger l’application sur votre ordinateur.
Votre application doit maintenant apparaître dans la liste des applications installées, prêtes à être lancées et testées !
Votre application Azure Functions et stockage terminée
Félicitations, vous avez créé une application de réalité mixte qui tire parti des services Azure Functions et Stockage Azure. Votre application pourra tirer parti des données stockées et fournir une action basée sur ces données.
Exercices bonus
Exercice 1
Créez un deuxième point de génération et un enregistrement à partir duquel un objet a été créé. Lorsque vous chargez le fichier de données, relectez les formes générées à partir de l’emplacement où elles ont été créées à l’origine.
Exercice 2
Créez un moyen de redémarrer l’application, plutôt que de devoir la rouvrir à chaque fois. Le chargement des scènes est un bon point de départ. Après cela, créez un moyen d’effacer la liste stockée dans Stockage Azure, afin qu’elle puisse être facilement réinitialisée à partir de votre application.