HoloLens (1. generace) a Azure 311 – Microsoft Graph

Poznámka

výukové kurzy Mixed reality Academy byly navržené pomocí HoloLens (1. generace) a smíšených sluchátek s ponořenými realitami. V takovém případě je důležité nechat tyto kurzy na místě pro vývojáře, kteří stále hledají pokyny k vývoji pro tato zařízení. tyto kurzy se neaktualizují na nejnovější sady nástrojů nebo interakce používané HoloLens 2. Budou zachovány, aby pokračovaly v práci na podporovaných zařízeních. v budoucnu bude k dispozici nová řada kurzů, které vám ukáže, jak vyvíjet HoloLens 2. Toto oznámení bude aktualizováno odkazem na tyto kurzy při jejich odeslání.

v tomto kurzu se naučíte, jak pomocí Microsoft Graph přihlašovat se k účet Microsoft pomocí zabezpečeného ověřování v rámci aplikace hybridní reality. Naplánovanou schůzku pak načtete a zobrazíte v aplikačním rozhraní.

Microsoft Graph je sada rozhraní api navržená tak, aby umožňovala přístup k mnoha službám microsoftu. Microsoft popisuje Microsoft Graph jako matrici prostředků propojených vztahy, což znamená, že aplikace umožňuje přístup k nejrůznějším datům připojených uživatelů. další informace najdete na stránce Microsoft Graph.

Vývoj bude zahrnovat vytvoření aplikace, ve které bude uživatel vyzván k pohledu v a potom klepněte na objekt sphere, který uživateli vyzve k bezpečnému přihlášení k účet Microsoft. Po přihlášení k účtu bude uživatel moci zobrazit seznam schůzek naplánovaných pro daný den.

po dokončení tohoto kurzu budete mít hybridní realitu HoloLens aplikaci, která bude moct provádět tyto akce:

  1. Pomocí gesta klepnutí klepněte na objekt, který uživateli vyzve k přihlášení k účtu Microsoft (přesunutí z aplikace za účelem přihlášení a opětovném obnovení do aplikace).
  2. Zobrazí seznam schůzek naplánovaných pro daný den.

Ve vaší aplikaci je až na to, jak budete výsledky integrovat s Vaším návrhem. Tento kurz je navržený tak, aby vám poučení, jak integrovat službu Azure s vaším projektem Unity. Je vaší úlohou použití znalostí, které získáte v tomto kurzu, abyste vylepšili vaši aplikaci ve smíšeném realitě.

Podpora zařízení

Kurz HoloLens Moderní sluchátka
MR a Azure 311: Microsoft Graph ✔️

Požadavky

Poznámka

Tento kurz je určený pro vývojáře, kteří mají základní zkušenosti s Unity a jazykem C#. Upozorňujeme také, že požadavky a písemné pokyny v tomto dokumentu označují, co bylo testováno a ověřeno v době psaní (červenec 2018). Můžete využívat nejnovější software, jak je uvedeno v článku Instalace nástrojů , i když by se vám nemělo předpokládat, že informace v tomto kurzu přesně odpovídají tomu, co najdete v novějším softwaru, než je uvedeno níže.

Pro tento kurz doporučujeme následující hardware a software:

Než začnete

  1. Chcete-li se vyhnout problémům při sestavování tohoto projektu, důrazně doporučujeme, abyste vytvořili projekt uvedený v tomto kurzu v kořenové nebo téměř kořenové složce (dlouhé cesty ke složkám mohou způsobovat problémy v době sestavení).
  2. Nastavte a otestujte své HoloLens. pokud potřebujete podporu při nastavení HoloLens, přečtěte si článek o nastavení HoloLens.
  3. při zahájení vývoje nové aplikace HoloLens je vhodné provést optimalizaci kalibrace a senzorů (někdy to může usnadnit provádění těchto úloh pro každého uživatele).

pokud potřebujete nápovědu k kalibraci, použijte prosím tento odkaz na článek HoloLens kalibrace.

pokud potřebujete nápovědu k optimalizaci senzorů, použijte prosím tento odkaz na článek ladění snímače HoloLens.

Kapitola 1 – Vytvoření aplikace na portálu pro registraci aplikací

Chcete-li začít, budete muset vytvořit a zaregistrovat aplikaci na portálu pro registraci aplikací.

v této kapitole najdete taky klíč služby, který vám umožní volat Microsoft Graph pro přístup k obsahu vašeho účtu.

  1. Přejděte na portál pro registraci aplikací od Microsoftu a přihlaste se pomocí svého účtu Microsoft. Jakmile se přihlásíte, budete přesměrováni na portál pro registraci aplikací.

  2. V části Moje aplikace klikněte na tlačítko Přidat aplikaci.

    Důležité

    Portál pro registraci aplikací může vypadat jinak, v závislosti na tom, zda jste již dříve pracovali s Microsoft Graph. Následující snímky obrazovky zobrazují tyto různé verze.

  3. Přidejte název aplikace a klikněte na vytvořit.

  4. Jakmile je aplikace vytvořená, budete přesměrováni na hlavní stránku aplikace. Zkopírujte ID aplikace a nezapomeňte tuto hodnotu poznamenat v bezpečí, později ji budete používat ve svém kódu.

  5. V části platformy se ujistěte, že se zobrazuje nativní aplikace . Pokud ne , klikněte na Přidat platformu a vyberte nativní aplikace.

  6. procházejte dolů na stejné stránce a v části s názvem Microsoft Graph oprávnění budete muset přidat další oprávnění pro aplikaci. Klikněte na Přidat vedle delegovaných oprávnění.

  7. Vzhledem k tomu, že chcete, aby aplikace měla přístup k kalendáři uživatele, zaškrtněte políčko s názvem kalendáře. Přečtěte si a klikněte na tlačítko OK.

  8. Posuňte se do dolní části a klikněte na tlačítko Uložit .

  9. Vaše uložení bude potvrzené a můžete se odhlásit z portálu pro registraci aplikací.

Kapitola 2 – nastavení projektu Unity

Toto je typická sada pro vývoj se smíšenými realitami a jako taková je dobrá šablona pro jiné projekty.

  1. Otevřete Unity a klikněte na Nový.

  2. Musíte zadat název projektu Unity. Vložte MSGraphMR. Ujistěte se, že je šablona projektu nastavená na 3D. Nastavte umístění , které je pro vás vhodné (Nezapomeňte, že blíž ke kořenovým adresářům je lepší). Pak klikněte na vytvořit projekt.

  3. V případě, že je aplikace Unity otevřená, je nutné zkontrolovat, že výchozí Editor skriptů je nastaven na Visual Studio. Přejděte na UpravitPředvolby a pak z nového okna přejděte k externím nástrojům. změňte Editor externích skriptů na Visual Studio 2017. Zavřete okno Předvolby .

  4. přejděte na souborBuild Nastavení a vyberte Univerzální platforma Windowsa potom klikněte na tlačítko přepnout platformu a použijte výběr.

  5. i když Nastavení sestavenísouborů, ujistěte se, že:

    1. Cílové zařízení je nastavené na HoloLens .

    2. Typ sestavení je nastavený na D3D .

    3. Sada SDK je nastavená na nejnovější verzi .

    4. verze Visual Studio je nastavená na nejnovější instalaci .

    5. Sestavení a spuštění je nastaveno na místní počítač .

    6. Uložte scénu a přidejte ji do sestavení.

      1. To uděláte tak, že vyberete Přidat otevřené scény. Zobrazí se okno Uložit.

      2. Vytvořte novou složku pro tuto a všechny budoucí scény. Kliknutím na tlačítko Nová složka vytvořte novou složku s názvem scény.

      3. Otevřete nově vytvořenou složku scény a potom do textového pole název souboru: zadejte MR_ComputerVisionScenea pak klikněte na Uložit.

        Důležité

        Uvědomte si, že je nutné uložit scény Unity do složky assety , protože musí být přidruženy k projektu Unity. Vytvoření složky scény (a dalších podobných složek) představuje typický způsob strukturování projektu Unity.

    7. zbývající nastavení v Nastavení sestaveníby měla být nyní ponechána jako výchozí.

  6. V okně buildu Nastavení klikněte na tlačítko Player Nastavení ( Player Nastavení). Otevře se související panel v prostoru, kde se nachází inspektor.

  7. Na tomto panelu je potřeba ověřit několik nastavení:

    1. Na kartě Nastavení:

      1. Verze skriptovacíhomodulu runtime by měla být Experimentální (ekvivalentní .NET 4.6), která aktivuje potřebu restartovat editor.

      2. Skriptovací back-end by měl být .NET.

      3. Úroveň kompatibility rozhraní API by měla být .NET 4.6.

    2. Na kartě Publishing Nastavení v části Schopnosti zaškrtněte:

      • InternetClient

    3. Dále na panelu v části XR Nastavení (viz níže Publikování Nastavení)zkontrolujte, jestli je virtuální realita podporovaná, a ujistěte se, že je Windows Mixed Reality SDK.

  8. V sestavě Nastaveníuž projekty Unity jazyka C# nejsou zašednuté. Zaškrtněte políčko vedle tohoto políčka.

  9. Zavřete okno Nastavení sestavení.

  10. Uložte scénu a projekt(SOUBORSAVE SCENES / FILESAVE PROJECT).

3. kapitola – Import knihoven v Unity

Důležité

Pokud chcete v tomto kurzu přeskočit komponentu Unity Set upapokračovat přímo do kódu, stáhněte si tento balíček Azure-MR-311.unitypackage,naimportujte ho do svého projektu jako vlastní balíček a pak pokračujte v kapitole 5.

Pokud chcete používat microsoft Graph v rámci Unity, musíte využít knihovnu DLL Microsoft.Identity.Client. Sadu Microsoft Graph SDK je možné použít, ale po sestavení projektu Unity bude vyžadovat přidání balíčku NuGet (tedy úpravu projektu po sestavení). Import požadovaných knihoven DLL přímo do Unity je považován za jednodušší.

Poznámka

V Unity aktuálně existuje známý problém, který vyžaduje, aby po importu byly moduly plug-in překonfigurované. Tyto kroky (4 až 7 v této části) už nebudou po vyřešení chyby potřeba.

Pokud chcete importovat Graph Microsoftu do vlastního projektu, stáhněte si MSGraph_LabPlugins.zip souboru. Tento balíček byl vytvořen s verzemi knihoven, které byly testovány.

Pokud se chcete dozvědět více o tom, jak do projektu Unity přidat vlastní knihovny DLL, použijte tento odkaz.

Import balíčku:

  1. Přidejte balíček Unity do Unity pomocí možnosti nabídky Vlastní balíček importu prostředků. Vyberte balíček, který jste právě stáhli.

  2. V poli Import Unity Package (Importovat balíček Unity), které se otevře, se ujistěte, že je vybrané všechno v části Moduly plug-in (včetně).

  3. Kliknutím na tlačítko Importovat přidejte položky do projektu.

  4. Přejděte do složky MSGraph v části Moduly plug-inna panelu Project a vyberte modul plug-in s názvem Microsoft.Identity.Client.

  5. S vybraným modulem plug-in se ujistěte, že není zaškrtnuté políčko Libovolná platforma, a pak zrušte zaškrtnutí políčka WSAPlayer a pak klikněte na Použít. To jenom potvrzuje, že jsou soubory správně nakonfigurované.

    Poznámka

    Označení těchto modulů plug-in je nakonfiguruje tak, aby se používaly jenom v Unity Editoru. Ve složce WSA existuje jiná sada knihoven DLL, které se budou používat po exportu projektu z Unity jako univerzální Windows aplikace.

  6. Dále musíte otevřít složku WSA ve složce MSGraph. Zobrazí se kopie stejného souboru, který jste právě nakonfigurovali. Vyberte soubor a pak v inspektoru:

    • Ujistěte se, že nenízaškrtnutépolíčko Libovolná platforma a že jezaškrtnuté jenomWSAPlayer.

    • Ujistěte se, že je sada SDK nastavená na UPWa back-end skriptování je nastavený na Tečkovací síť.

    • Ujistěte se, že je zaškrtnuté políčkoNezpracujte.

  7. Klikněte na Použít.

4. kapitola – Nastavení kamery

V této kapitole nastavíte hlavní kameru scény:

  1. Na panelu Hierarchievyberte hlavní kameru.

  2. Po výběru této položky se na panelu inspektoru zobrazí všechny komponenty hlavní kamery.

    1. Objekt Fotoaparát musí mít název Hlavní kamera (všimněte si pravopisu).

    2. Značka hlavní kamery musí být nastavená na MainCamera (poznamenejte si pravopis).)

    3. Ujistěte se, že je pozice transformace nastavená na 0, 0, 0.

    4. Nastavte možnost Vymazat příznaky na plnou barvu.

    5. Nastavte barvu pozadí komponenty fotoaparátu na černou, alfa 0(šestnáctkové číslo: #00000000).

  3. Konečná struktura objektu v hierarchickém panelu by měla být podobná struktuře znázorněné na následujícím obrázku:

5. kapitola – vytvoření třídy MeetingsUI

Prvním skriptem, který je potřeba vytvořit, je MeetingsUI, který zodpovídá za hostování a naplnění uživatelského rozhraní aplikace (uvítací zpráva, pokyny a podrobnosti schůzek).

Vytvoření této třídy:

  1. Klikněte pravým tlačítkem na složku Assets(Prostředky) na panelu Project apak vyberte Create Folder (Vytvořit složku). Složku pojmechte Scripts (Skripty).

  2. Otevřete složku Scripts a pak v této složce klikněte pravým tlačítkem na Create C# Script (Vytvořitskript C#). Pojmete skript MeetingsUI.

  3. Poklikejte na nový skript MeetingsUI a otevřete ho pomocí Visual Studio.

  4. Vložte následující obory názvů:

    using System;
    using UnityEngine;
    
  5. Do třídy vložte následující proměnné:

        /// <summary>
        /// Allows this class to behave like a singleton
        /// </summary>
        public static MeetingsUI Instance;
    
        /// <summary>
        /// The 3D text of the scene
        /// </summary>
        private TextMesh _meetingDisplayTextMesh;
    
  6. Potom nahraďte metodu Start() a přidejte metodu Awake(). Ty budou volány při inicializaci třídy:

        /// <summary>
        /// Called on initialization
        /// </summary>
        void Awake()
        {
            Instance = this;
        }
    
        /// <summary>
        /// Called on initialization, after Awake
        /// </summary>
        void Start ()
        {
            // Creating the text mesh within the scene
            _meetingDisplayTextMesh = CreateMeetingsDisplay();
        }
    
  7. Přidejte metody zodpovědné za vytvoření uživatelského rozhraní Schůzky a na vyžádání do něj vyplňte aktuální schůzky:

        /// <summary>
        /// Set the welcome message for the user
        /// </summary>
        internal void WelcomeUser(string userName)
        {
            if(!string.IsNullOrEmpty(userName))
            {
                _meetingDisplayTextMesh.text = $"Welcome {userName}";
            }
            else 
            {
                _meetingDisplayTextMesh.text = "Welcome";
            }
        }
    
        /// <summary>
        /// Set up the parameters for the UI text
        /// </summary>
        /// <returns>Returns the 3D text in the scene</returns>
        private TextMesh CreateMeetingsDisplay()
        {
            GameObject display = new GameObject();
            display.transform.localScale = new Vector3(0.03f, 0.03f, 0.03f);
            display.transform.position = new Vector3(-3.5f, 2f, 9f);
            TextMesh textMesh = display.AddComponent<TextMesh>();
            textMesh.anchor = TextAnchor.MiddleLeft;
            textMesh.alignment = TextAlignment.Left;
            textMesh.fontSize = 80;
            textMesh.text = "Welcome! \nPlease gaze at the button" +
                "\nand use the Tap Gesture to display your meetings";
    
            return textMesh;
        }
    
        /// <summary>
        /// Adds a new Meeting in the UI by chaining the existing UI text
        /// </summary>
        internal void AddMeeting(string subject, DateTime dateTime, string location)
        {
            string newText = $"\n{_meetingDisplayTextMesh.text}\n\n Meeting,\nSubject: {subject},\nToday at {dateTime},\nLocation: {location}";
    
            _meetingDisplayTextMesh.text = newText;
        }
    
  8. Odstraňtemetodu Update() a před návratem do Unity Visual Studio změny v souboru .

6. kapitola – vytvoření Graph třídy

Dalším skriptem, který se má vytvořit, je Graph skript. Tento skript zodpovídá za volání pro ověření uživatele a načtení plánovaných schůzek pro aktuální den z kalendáře uživatele.

Vytvoření této třídy:

  1. Poklikejte na složku Scripts (Skripty) a otevřete ji.

  2. Klikněte pravým tlačítkem do složky Scripts a pak klikněte na Create C# Script (Vytvořitskript C#). Pojmete skript Graph.

  3. Poklikejte na skript a otevřete ho pomocí Visual Studio.

  4. Vložte následující obory názvů:

    using System.Collections.Generic;
    using UnityEngine;
    using Microsoft.Identity.Client;
    using System;
    using System.Threading.Tasks;
    
    #if !UNITY_EDITOR && UNITY_WSA
    using System.Net.Http;
    using System.Net.Http.Headers;
    using Windows.Storage;
    #endif
    

    Důležité

    Všimněte si, že části kódu v tomto skriptu jsou zabalené kolem direktiv předkompilování ,aby se zabránilo problémům s knihovnami při sestavování Visual Studio řešení.

  5. Odstraňte metody Start() a Update(), protože se nebudou používat.

  6. Mimo Graph třídy vložte následující objekty, které jsou nezbytné k deserializaci objektu JSON představujícího každodenní naplánované schůzky:

    /// <summary>
    /// The object hosting the scheduled meetings
    /// </summary>
    [Serializable]
    public class Rootobject
    {
        public List<Value> value;
    }
    
    [Serializable]
    public class Value
    {
        public string subject { get; set; }
        public StartTime start { get; set; }
        public Location location { get; set; }
    }
    
    [Serializable]
    public class StartTime
    {
        public string dateTime;
    
        private DateTime? _startDateTime;
        public DateTime StartDateTime
        {
            get
            {
                if (_startDateTime != null)
                    return _startDateTime.Value;
                DateTime dt;
                DateTime.TryParse(dateTime, out dt);
                _startDateTime = dt;
                return _startDateTime.Value;
            }
        }
    }
    
    [Serializable]
    public class Location
    {
        public string displayName { get; set; }
    }
    
  7. Do Graph přidejte následující proměnné:

        /// <summary>
        /// Insert your Application Id here
        /// </summary>
        private string _appId = "-- Insert your Application Id here --";
    
        /// <summary>
        /// Application scopes, determine Microsoft Graph accessibility level to user account
        /// </summary>
        private IEnumerable<string> _scopes = new List<string>() { "User.Read", "Calendars.Read" };
    
        /// <summary>
        /// Microsoft Graph API, user reference
        /// </summary>
        private PublicClientApplication _client;
    
        /// <summary>
        /// Microsoft Graph API, authentication
        /// </summary>
        private AuthenticationResult _authResult;
    
    

    Poznámka

    Změňte hodnotu appId na ID aplikace, které jste si v kapitole 1, kroku 4. Tato hodnota by měla být stejná jako ta, která se zobrazuje na portálu pro registraci aplikací na stránce registrace aplikace.

  8. Do Graph přidejte metody SignInAsync() a AquireTokenAsync(),které vyzve uživatele k vložení přihlašovacích údajů.

        /// <summary>
        /// Begin the Sign In process using Microsoft Graph Library
        /// </summary>
        internal async void SignInAsync()
        {
    #if !UNITY_EDITOR && UNITY_WSA
            // Set up Grap user settings, determine if needs auth
            ApplicationDataContainer localSettings = ApplicationData.Current.LocalSettings;
            string userId = localSettings.Values["UserId"] as string;
            _client = new PublicClientApplication(_appId);
    
            // Attempt authentication
            _authResult = await AcquireTokenAsync(_client, _scopes, userId);
    
            // If authentication is successful, retrieve the meetings
            if (!string.IsNullOrEmpty(_authResult.AccessToken))
            {
                // Once Auth as been completed, find the meetings for the day
                await ListMeetingsAsync(_authResult.AccessToken);
            }
    #endif
        }
    
        /// <summary>
        /// Attempt to retrieve the Access Token by either retrieving
        /// previously stored credentials or by prompting user to Login
        /// </summary>
        private async Task<AuthenticationResult> AcquireTokenAsync(
            IPublicClientApplication app, IEnumerable<string> scopes, string userId)
        {
            IUser user = !string.IsNullOrEmpty(userId) ? app.GetUser(userId) : null;
            string userName = user != null ? user.Name : "null";
    
            // Once the User name is found, display it as a welcome message
            MeetingsUI.Instance.WelcomeUser(userName);
    
            // Attempt to Log In the user with a pre-stored token. Only happens
            // in case the user Logged In with this app on this device previously
            try
            {
                _authResult = await app.AcquireTokenSilentAsync(scopes, user);
            }
            catch (MsalUiRequiredException)
            {
                // Pre-stored token not found, prompt the user to log-in 
                try
                {
                    _authResult = await app.AcquireTokenAsync(scopes);
                }
                catch (MsalException msalex)
                {
                    Debug.Log($"Error Acquiring Token: {msalex.Message}");
                    return _authResult;
                }
            }
    
            MeetingsUI.Instance.WelcomeUser(_authResult.User.Name);
    
    #if !UNITY_EDITOR && UNITY_WSA
            ApplicationData.Current.LocalSettings.Values["UserId"] = 
            _authResult.User.Identifier;
    #endif
            return _authResult;
        }
    
  9. Přidejte následující dvě metody:

    1. BuildTodayCalendarEndpoint(), který sestaví identifikátor URI určující den a časové období, ve kterém se načítá naplánované schůzky.

    2. ListMeetingsAsync(),která požaduje naplánované schůzky od Microsoftu Graph.

        /// <summary>
        /// Build the endpoint to retrieve the meetings for the current day.
        /// </summary>
        /// <returns>Returns the Calendar Endpoint</returns>
        public string BuildTodayCalendarEndpoint()
        {
            DateTime startOfTheDay = DateTime.Today.AddDays(0);
            DateTime endOfTheDay = DateTime.Today.AddDays(1);
            DateTime startOfTheDayUTC = startOfTheDay.ToUniversalTime();
            DateTime endOfTheDayUTC = endOfTheDay.ToUniversalTime();
    
            string todayDate = startOfTheDayUTC.ToString("o");
            string tomorrowDate = endOfTheDayUTC.ToString("o");
            string todayCalendarEndpoint = string.Format(
                "https://graph.microsoft.com/v1.0/me/calendarview?startdatetime={0}&enddatetime={1}",
                todayDate,
                tomorrowDate);
    
            return todayCalendarEndpoint;
        }
    
        /// <summary>
        /// Request all the scheduled meetings for the current day.
        /// </summary>
        private async Task ListMeetingsAsync(string accessToken)
        {
    #if !UNITY_EDITOR && UNITY_WSA
            var http = new HttpClient();
    
            http.DefaultRequestHeaders.Authorization = 
            new AuthenticationHeaderValue("Bearer", accessToken);
            var response = await http.GetAsync(BuildTodayCalendarEndpoint());
    
            var jsonResponse = await response.Content.ReadAsStringAsync();
    
            Rootobject rootObject = new Rootobject();
            try
            {
                // Parse the JSON response.
                rootObject = JsonUtility.FromJson<Rootobject>(jsonResponse);
    
                // Sort the meeting list by starting time.
                rootObject.value.Sort((x, y) => DateTime.Compare(x.start.StartDateTime, y.start.StartDateTime));
    
                // Populate the UI with the meetings.
                for (int i = 0; i < rootObject.value.Count; i++)
                {
                    MeetingsUI.Instance.AddMeeting(rootObject.value[i].subject,
                                                rootObject.value[i].start.StartDateTime.ToLocalTime(),
                                                rootObject.value[i].location.displayName);
                }
            }
            catch (Exception ex)
            {
                Debug.Log($"Error = {ex.Message}");
                return;
            }
    #endif
        }
    
  10. Právě jste dokončili Graph skriptu. Než se vrátíte do Unity, Visual Studio změny uložte v souboru .

7. kapitola – vytvoření skriptu Pohledu

Teď vytvoříte prvek GazeInput. Tato třída zpracovává a sleduje pohled uživatele pomocí raycastu přicházející z hlavní kamery aprojektování vpřed.

Vytvoření skriptu:

  1. Poklikejte na složku Scripts (Skripty) a otevřete ji.

  2. Klikněte pravým tlačítkem do složky Scripts a pak klikněte na Create C# Script (Vytvořitskript C#). Pojmete skript GazeInput.

  3. Poklikejte na skript a otevřete ho pomocí Visual Studio.

  4. Změňte kód oborů názvů tak, aby odpovídal kódu uvedenému níže, a přidejte značku[System.Serializable]nad třídu GazeInput, aby ji bylo možné serializovat:

    using UnityEngine;
    
    /// <summary>
    /// Class responsible for the User's Gaze interactions
    /// </summary>
    [System.Serializable]
    public class GazeInput : MonoBehaviour
    {
    
  5. Do třídy GazeInput přidejte následující proměnné:

        [Tooltip("Used to compare whether an object is to be interacted with.")]
        internal string InteractibleTag = "SignInButton";
    
        /// <summary>
        /// Length of the gaze
        /// </summary>
        internal float GazeMaxDistance = 300;
    
        /// <summary>
        /// Object currently gazed
        /// </summary>
        internal GameObject FocusedObject { get; private set; }
    
        internal GameObject oldFocusedObject { get; private set; }
    
        internal RaycastHit HitInfo { get; private set; }
    
        /// <summary>
        /// Cursor object visible in the scene
        /// </summary>
        internal GameObject Cursor { get; private set; }
    
        internal bool Hit { get; private set; }
    
        internal Vector3 Position { get; private set; }
    
        internal Vector3 Normal { get; private set; }
    
        private Vector3 _gazeOrigin;
    
        private Vector3 _gazeDirection;
    
  6. Přidejte metodu CreateCursor() pro vytvoření HoloLens kurzoru ve scéně a zavolejte metodu z metody Start():

        /// <summary>
        /// Start method used upon initialisation.
        /// </summary>
        internal virtual void Start()
        {
            FocusedObject = null;
            Cursor = CreateCursor();
        }
    
        /// <summary>
        /// Method to create a cursor object.
        /// </summary>
        internal 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 = new Vector3(0.05f, 0.05f, 0.05f);
            Material mat = new Material(Shader.Find("Diffuse"));
            newCursor.GetComponent<MeshRenderer>().material = mat;
            mat.color = Color.HSVToRGB(0.0223f, 0.7922f, 1.000f);
            newCursor.SetActive(true);
    
            return newCursor;
        }
    
  7. Následující metody umožňují sledovat Raycast a sledovat zaměřené objekty.

    /// <summary>
    /// Called every frame
    /// </summary>
    internal virtual void Update()
    {
        _gazeOrigin = Camera.main.transform.position;
    
        _gazeDirection = Camera.main.transform.forward;
    
        UpdateRaycast();
    }
    /// <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))
            {
                // Provide the 'Gaze Exited' event.
                oldFocusedObject.SendMessage("OnGazeExited", SendMessageOptions.DontRequireReceiver);
            }
        }
    }
    
        private void UpdateRaycast()
        {
            // Set the old focused gameobject.
            oldFocusedObject = FocusedObject;
            RaycastHit hitInfo;
    
            // Initialise Raycasting.
            Hit = Physics.Raycast(_gazeOrigin,
                _gazeDirection,
                out hitInfo,
                GazeMaxDistance);
                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. If so, reset the focused object.
            if (FocusedObject != oldFocusedObject)
            {
                ResetFocusedObject();
                if (FocusedObject != null)
                {
                    if (FocusedObject.CompareTag(InteractibleTag))
                    {
                        // Provide the 'Gaze Entered' event.
                        FocusedObject.SendMessage("OnGazeEntered", 
                            SendMessageOptions.DontRequireReceiver);
                    }
                }
            }
        }
    
  8. Než se vrátíte do Unity, Visual Studio změny uložte v souboru .

Kapitola 8 – vytvoření třídy Interactions

Teď budete muset vytvořit skript Interakce, který zodpovídá za:

  • Zpracování interakcí klepnutím a pohledu na fotoaparát,který umožňuje uživateli pracovat s přihlášením k "tlačítku" ve scéně.

  • Vytvoření objektu log ve scéně pro interakci uživatele

Vytvoření skriptu:

  1. Poklikejte na složku Scripts (Skripty) a otevřete ji.

  2. Klikněte pravým tlačítkem do složky Scripts a pak klikněte na Create C# Script (Vytvořitskript C#). Pojmete skript Interactions (Interakce).

  3. Poklikejte na skript a otevřete ho pomocí Visual Studio.

  4. Vložte následující obory názvů:

    using UnityEngine;
    using UnityEngine.XR.WSA.Input;
    
  5. Změňte dědičnost třídy Interaction z MonoBehaviour naGazeInput.

    Interakce veřejné třídy: MonoBehaviour

    public class Interactions : GazeInput
    
  6. Do třídy Interaction vložte následující proměnnou:

        /// <summary>
        /// Allows input recognition with the HoloLens
        /// </summary>
        private GestureRecognizer _gestureRecognizer;
    
  7. Nahraďte metodu Start. Všimněte si, že se jedná o metodu přepsání, která volá metodu třídy "base" Pohled. Metoda Start() se volá při inicializaci třídy, registraci pro rozpoznávání vstupu a vytvoření tlačítka pro přihlášení ve scéně:

        /// <summary>
        /// Called on initialization, after Awake
        /// </summary>
        internal override void Start()
        {
            base.Start();
    
            // Register the application to recognize HoloLens user inputs
            _gestureRecognizer = new GestureRecognizer();
            _gestureRecognizer.SetRecognizableGestures(GestureSettings.Tap);
            _gestureRecognizer.Tapped += GestureRecognizer_Tapped;
            _gestureRecognizer.StartCapturingGestures();
    
            // Add the Graph script to this object
            gameObject.AddComponent<MeetingsUI>();
            CreateSignInButton();
        }
    
  8. Přidejte metodu CreateSignInButton(), která vytvoří instanci tlačítka pro přihlášení ve scéně a nastaví její vlastnosti:

        /// <summary>
        /// Create the sign in button object in the scene
        /// and sets its properties
        /// </summary>
        void CreateSignInButton()
        {
            GameObject signInButton = GameObject.CreatePrimitive(PrimitiveType.Sphere);
    
            Material mat = new Material(Shader.Find("Diffuse"));
            signInButton.GetComponent<Renderer>().material = mat;
            mat.color = Color.blue;
    
            signInButton.transform.position = new Vector3(3.5f, 2f, 9f);
            signInButton.tag = "SignInButton";
            signInButton.AddComponent<Graph>();
        }
    
  9. Přidejte metodu GestureRecognizer_Tapped(), která bude reagovat na událost uživatele Klepnutím.

        /// <summary>
        /// Detects the User Tap Input
        /// </summary>
        private void GestureRecognizer_Tapped(TappedEventArgs obj)
        {
            if(base.FocusedObject != null)
            {
                Debug.Log($"TAP on {base.FocusedObject.name}");
                base.FocusedObject.SendMessage("SignInAsync", SendMessageOptions.RequireReceiver);
            }
        }
    
  10. Odstraňtemetodu Update() a pak změny uložte do souboru Visual Studio a pak se vraťte do Unity.

Kapitola 9 – Nastavení odkazů na skripty

V této kapitole je potřeba umístit skript Interakce do hlavní kamery. Tento skript pak zřídí umístění dalších skriptů tam, kde je potřeba.

  • Ze složky Skripty na panelu Project přetáhněteskript Interakce do objektu Hlavní kamera, jak je na obrázku níže.

Kapitola 10 – Nastavení značky

Kód, který zachytá pohled, použije značku SignInButton k identifikaci objektu, se kterým bude uživatel pracovat při přihlašování k Microsoft Graph.

Vytvoření značky:

  1. V editoru Unity klikněte na hlavní kameru v hierarchickém panelu.

  2. Na panelu inspektoru kliknutím na značku MainCamera otevřete rozevírací seznam. Klikněte na Přidat značku...

  3. Klikněte na + tlačítko .

  4. Jako Název značky zadejte SignInButton a klikněte na Uložit.

11. kapitola – Sestavení projektu Unity pro UPW

Všechno potřebné pro část Unity tohoto projektu je teď hotové, takže je čas ji sestavit z Unity.

  1. Přejděte na Build Nastavení (FileBuild Nastavení).

  2. Pokud to ještě není, zaškrtněte Unity C# Projects ( Projekty Unity v jazyce C#).

  3. Klikněte na Build (Sestavit). Unity spustí Průzkumník souborů, ve kterém budete muset vytvořit a pak vybrat složku, do které chcete aplikaci sestavit. Teď vytvořte složku a pojmnte ji App (Aplikace). Potom s vybranou možností Složka aplikace klikněte na Vybrat složku.

  4. Unity začne vytvářet projekt do složky App.

  5. Jakmile Unity dokončí sestavování (může to chvíli trvat), otevře se v umístění sestavení okno Průzkumník souborů (podívejte se na hlavní panel, protože se nemusí vždy zobrazovat nad okny, ale upozorní vás na přidání nového okna).

12. kapitola – nasazení do HoloLens

Nasazení na HoloLens:

  1. Budete potřebovat IP adresu vaší aplikace HoloLens (pro vzdálené nasazení) a zajistit, aby HoloLens byla v režimu pro vývojáře. Chcete-li to provést:

    1. Když máte HoloLens, otevřete Nastavení.

    2. Přejděte na Síť Internet>>>>

    3. Poznamenejte si IPv4 adresu.

    4. Pak přejděte zpět na Nastavenía pak na Aktualizace zabezpečenípro vývojáře.

    5. Nastavte vývojářský režim na.

  2. Přejděte k novému sestavení Unity (složce App) a otevřete soubor řešení pomocí Visual Studio.

  3. V části Konfigurace řešení vyberte Ladit.

  4. V platformě řešenívyberte x86, vzdálený počítač. Zobrazí se výzva k vložení IP adresy vzdáleného zařízení (HoloLens, v tomto případě, kterou jste si už vložili).

  5. Přejděte do nabídky Build (Sestavení) a kliknutím na Deploy Solution (Nasadit řešení) aplikaci bokem načtou do HoloLens.

  6. Vaše aplikace by se teď měla zobrazit v seznamu nainstalovaných aplikací v HoloLens, které jsou připravené ke spuštění.

Vaše aplikace Microsoft Graph HoloLens

Blahopřejeme, máte vytvořenou aplikaci hybridní reality, která využívá rozhraní Microsoft Graph ke čtení a zobrazení dat kalendáře uživatele.

Bonusová cvičení

Cvičení 1

Použití služby Microsoft Graph k zobrazení dalších informací o uživateli

  • E-mail uživatele, telefonní číslo nebo profilový obrázek

Cvičení 1

Implementujte hlasové ovládání pro navigaci v uživatelském Graph Microsoftu.