311. HoloLens (1-го поколения) и Azure — Microsoft Graph

Примечание

Руководства Mixed Reality Academy были разработаны для иммерсивных гарнитур HoloLens (1-го поколения) и иммерсивных гарнитур Mixed Reality. Поэтому мы считаем, что важно оставить эти руководства для разработчиков, которые ищут рекомендации по разработке для этих устройств. Данные руководства не будут обновляться с учетом последних наборов инструментов или возможностей взаимодействия для HoloLens 2. Они будут сохранены для работы на поддерживаемых устройствах. В будущем будет опубликована новая серия учебников, демонстрирующих разработку для HoloLens 2. В этом уведомлении будет добавлена ссылка на эти руководства при их публикации.

В этом курсе вы узнаете, как использовать Microsoft Graph для входа в учетную запись Майкрософт с помощью безопасной проверки подлинности в приложении смешанной реальности. Затем вы получите и отобразите запланированные собрания в интерфейсе приложения.

Снимок экрана: запланированные собрания в интерфейсе приложения.

Microsoft Graph — это набор API, предназначенный для предоставления доступа ко многим службам Майкрософт. Корпорация Майкрософт описывает Microsoft Graph как матрицу ресурсов, соединенных связями, что позволяет приложению получать доступ ко всем видам подключенных пользовательских данных. Дополнительные сведения см. на странице Microsoft Graph.

Разработка будет включать создание приложения, в котором пользователю будет предложено взглянуть на сферу, а затем коснуться сферы, которая предложит пользователю безопасно войти в учетную запись Майкрософт. После входа в свою учетную запись пользователь сможет просмотреть список собраний, запланированных на день.

После прохождения этого курса вы получите приложение HoloLens смешанной реальности, которое сможет выполнять следующие действия:

  1. С помощью жеста Касание коснитесь объекта , который предложит пользователю войти в учетную запись Майкрософт (выйдите из приложения, чтобы войти в систему, а затем снова в приложение).
  2. Просмотр списка собраний, запланированных на день.

В приложении вы определяете, как вы будете интегрировать результаты в проект. Этот курс предназначен для обучения интеграции службы Azure с проектом Unity. Ваша задача — использовать знания, полученные из этого курса, для улучшения приложения смешанной реальности.

Поддержка устройств

Курс HoloLens Иммерсивные гарнитуры
311. Смешанная реальность и Azure: Microsoft Graph ✔️

Предварительные требования

Примечание

Это руководство предназначено для разработчиков, имеющих базовый опыт работы с Unity и C#. Кроме того, имейте в виду, что предварительные требования и письменные инструкции в этом документе представляют то, что было протестировано и проверено на момент написания статьи (июль 2018 г.). Вы можете использовать последнюю версию программного обеспечения, как указано в статье установка инструментов , хотя не следует предполагать, что информация в этом курсе будет идеально соответствовать тому, что вы найдете в более новом программном обеспечении, чем указано ниже.

Для этого курса мы рекомендуем использовать следующее оборудование и программное обеспечение:

Перед началом работы

  1. Чтобы избежать проблем со сборкой этого проекта, настоятельно рекомендуется создать проект, упомянутый в этом руководстве, в корневой или почти корневой папке (длинные пути к папкам могут вызвать проблемы во время сборки).
  2. Настройте и протестируйте HoloLens. Если вам нужна поддержка по настройке HoloLens, обязательно ознакомьтесь со статьей о настройке HoloLens.
  3. Рекомендуется выполнять калибровку и настройку датчиков при разработке нового приложения HoloLens (иногда это может помочь выполнить эти задачи для каждого пользователя).

Для получения справки по калибровке перейдите по этой ссылке на статью Калибровка HoloLens.

Чтобы получить справку по настройке датчика, перейдите по этой ссылке на статью Настройка датчика HoloLens.

Глава 1. Создание приложения на портале регистрации приложений

Для начала необходимо создать и зарегистрировать приложение на портале регистрации приложений.

В этой главе вы также найдете ключ службы, который позволит выполнять вызовы Microsoft Graph для доступа к содержимому учетной записи.

  1. Перейдите на портал регистрации приложений Майкрософт и войдите с помощью учетной записи Майкрософт. После входа вы будете перенаправлены на портал регистрации приложений.

  2. В разделе Мои приложения нажмите кнопку Добавить приложение.

    Снимок экрана, на котором показано, где нажать кнопку Добавить приложение.

    Важно!

    Портал регистрации приложений может выглядеть по-разному в зависимости от того, работали ли вы с Microsoft Graph ранее. На снимках экрана ниже показаны различные версии.

  3. Добавьте имя приложения и нажмите кнопку Создать.

    Снимок экрана, на котором показано, где можно добавить имя для приложения.

  4. После создания приложения вы будете перенаправлены на страницу main приложения. Скопируйте идентификатор приложения и обязательно запишите это значение в безопасном месте. Скоро вы будете использовать его в коде.

    Снимок экрана: место для просмотра идентификатора приложения.

  5. В разделе Платформы убедитесь, что отображается собственное приложение . Если нет , щелкните Add Platform (Добавить платформу ) и выберите Native Application (Собственное приложение).

    Снимок экрана, на котором выделен раздел

  6. Прокрутите страницу вниз и в разделе Разрешения Microsoft Graph вам потребуется добавить дополнительные разрешения для приложения. Щелкните Добавить рядом с пунктом Делегированные разрешения.

    Снимок экрана, на котором показано, где нажать кнопку Добавить рядом с пунктом Делегированные разрешения.

  7. Так как вы хотите, чтобы приложение пользовалось календарем пользователя, проверка поле Calendars.Read и нажмите кнопку ОК.

    Снимок экрана: флажок Calendars.Read.

  8. Прокрутите страницу вниз и нажмите кнопку Сохранить .

    Снимок экрана, на котором показано, где нажать кнопку Сохранить.

  9. Сохранение будет подтверждено, и вы сможете выйти из системы на портале регистрации приложений.

Глава 2. Настройка проекта Unity

Ниже приведена типичная настройка для разработки со смешанной реальностью и, таким образом, хороший шаблон для других проектов.

  1. Откройте Unity и нажмите кнопку Создать.

    Снимок экрана: интерфейс Unity.

  2. Необходимо указать имя проекта Unity. Вставьте MSGraphMR. Убедитесь, что для шаблона проекта задано значение 3D. Задайте для параметра Расположение подходящее место (помните, что лучше ближе к корневым каталогам). Затем щелкните Создать проект.

    Снимок экрана, на котором показано, где нажать кнопку Создать проект.

  3. При открытии Unity стоит проверить, что для редактора скриптов по умолчанию задано значение Visual Studio. Перейдите в раздел Изменение>параметров , а затем в новом окне перейдите к разделу Внешние инструменты. Измените внешний редактор скриптов на Visual Studio 2017. Закройте окно Параметры .

    Снимок экрана: установка visual Studio 2017 для внешнего редактора скриптов.

  4. Перейдите враздел Параметры сборкифайла> и выберите универсальная платформа Windows, а затем нажмите кнопку Переключить платформу, чтобы применить выбранный вариант.

    Снимок экрана, на котором показано, где выбрать пункт Переключить платформу.

  5. Оставаясь впараметрах сборкифайла>, убедитесь, что:

    1. Для целевого устройствазадано значение HoloLens

    2. Для параметра Тип сборки задано значение D3D.

    3. Для пакета SDK задано значение Последняя установленная

    4. Для версии Visual Studio задано значение Последняя установленная версия

    5. Для сборки и запуска задано значение Локальный компьютер.

    6. Сохраните сцену и добавьте ее в сборку.

      1. Для этого выберите Добавить открытые сцены. Появится окно сохранения.

        Снимок экрана, на котором показано, где выбрать команду Добавить открытые сцены.

      2. Создайте новую папку для этой и любой будущей сцены. Нажмите кнопку Создать папку , чтобы создать новую папку, назовите ее Scenes.

        Снимок экрана, на котором показано, где присвоить имя новой папке.

      3. Откройте только что созданную папку Scenes , а затем в текстовом поле Имя файла введите MR_ComputerVisionScene, а затем нажмите кнопку Сохранить.

        Снимок экрана, на котором показано, где ввести имя файла.

        Важно!

        Имейте в виду, что сцены Unity необходимо сохранить в папке Assets , так как они должны быть связаны с проектом Unity. Создание папки scenes (и других аналогичных папок) — типичный способ структурирования проекта Unity.

    7. Оставшиеся параметры в разделе Параметры сборки на данный момент следует оставить по умолчанию.

  6. В окне Параметры сборки нажмите кнопку Параметры проигрывателя . Откроется соответствующая панель в пространстве, где находится инспектор .

    Снимок экрана: диалоговое окно

  7. На этой панели необходимо проверить несколько параметров:

    1. На вкладке Другие параметры :

      1. Версия среды выполнениясценариев должна быть экспериментальной (эквивалент .NET 4.6), что вызовет необходимость перезапуска редактора.

      2. Серверная часть сценариев должна быть .NET

      3. Уровень совместимости API должен быть .NET 4.6

        Снимок экрана, на котором показано, где проверка уровень совместимости API.

    2. На вкладке Параметры публикации в разделе Возможности проверка:

      • InternetClient;

        Снимок экрана, на котором показано, где выбрать параметр InternetClient.

    3. Далее вниз по панели в разделе Параметры XR (см. раздел Параметры публикации) проверка Virtual Reality Supported (Поддерживается виртуальная реальность) убедитесь, что добавлен пакет SDK для Windows Mixed Reality.

      Снимок экрана: место добавления пакета SDK для Windows Mixed Reality.

  8. Вернувшись в параметры сборки, проекты Unity C# больше не выделены серым цветом; проверка флажок рядом с этим.

  9. Закройте окно Build Settings (Параметры сборки).

  10. Сохраните сцену и проект (FILE>SAVE SCENES / FILE>SAVE PROJECT).

Глава 3. Импорт библиотек в Unity

Важно!

Если вы хотите пропустить компонент настройки Unity этого курса и перейти непосредственно к коду, скачайте этот пакет Azure-MR-311.unitypackage, импортируйте его в проект в виде пользовательского пакета, а затем перейдите к главе 5.

Чтобы использовать Microsoft Graph в Unity, необходимо использовать библиотеку DLL Microsoft.Identity.Client . Можно использовать пакет SDK Microsoft Graph, однако после сборки проекта Unity потребуется добавить пакет NuGet (то есть изменить проект после сборки). Считается проще импортировать необходимые библиотеки DLL непосредственно в Unity.

Примечание

В настоящее время в Unity существует известная проблема, которая требует перенастройки подключаемых модулей после импорта. Эти действия (4–7 в этом разделе) больше не требуются после устранения ошибки.

Чтобы импортировать Microsoft Graph в собственный проект, скачайте файл MSGraph_LabPlugins.zip. Этот пакет был создан с версиями библиотек, которые были протестированы.

Если вы хотите узнать больше о том, как добавить пользовательские библиотеки DLL в проект Unity, перейдите по этой ссылке.

Чтобы импортировать пакет, выполните следующие действия.

  1. Добавьте пакет Unity в Unity с помощью пункта менюИмпорт пакета>ресурсов>Пользовательский пакет. Выберите пакет, который вы только что скачали.

  2. В появившемся окне Импорт пакета Unity убедитесь, что выбрано все содержимое в разделе (и в том числе) Подключаемые модули .

    Снимок экрана: выбранные параметры конфигурации в разделе Подключаемые модули.

  3. Нажмите кнопку Импорт , чтобы добавить элементы в проект.

  4. Перейдите в папку MSGraph в разделе Подключаемые модули на панели проекта и выберите подключаемый модуль с именем Microsoft.Identity.Client.

    Снимок экрана: подключаемый модуль Microsoft.Identity.Client.

  5. Выбрав подключаемый модуль , снимите флажок Любая платформа , а затем снимите флажок WSAPlayer , а затем нажмите кнопку Применить. Это просто для подтверждения правильности настройки файлов.

    Снимок экрана, на котором показано, где можно подтвердить, что не установлен флажок Any Platform и WSAPlayer.

    Примечание

    Помечая эти подключаемые модули, они будут использоваться только в редакторе Unity. В папке WSA есть другой набор библиотек DLL, которые будут использоваться после экспорта проекта из Unity в качестве универсального приложения для Windows.

  6. Затем необходимо открыть папку WSA в папке MSGraph . Вы увидите копию того же файла, который вы только что настроили. Выберите файл, а затем в инспекторе:

    • убедитесь, что флажок Любая платформаснят и установлен толькоWSAPlayer.

    • Убедитесь, что для пакета SDK задано значение UWP, а серверная часть сценариевDot Net.

    • Убедитесь, что установлен флажокНе обрабатывать.

      Снимок экрана, на котором показано, что выбран параметр Не обрабатывать.

  7. Щелкните Применить.

Глава 4. Настройка камеры

В рамках этой главы вы настроите главную камеру сцены:

  1. На панели Иерархия выберите основную камеру.

  2. После выбора вы увидите все компоненты основной камеры на панели Инспектор .

    1. Объект Camera должен называться Main Camera (обратите внимание на орфографию!)

    2. Для тега основной камеры необходимо задать значение MainCamera (обратите внимание на орфографию!)

    3. Убедитесь, что для позиции преобразования задано значение 0, 0, 0.

    4. Для параметра Очистить флаги установлено значение Сплошной цвет

    5. Задайте для параметра Цвет фона компонента камеры значение Черный, Альфа 0(Шестнадцатеричный код: #00000000)

      Снимок экрана, на котором показано, где следует задать цвет фона.

  3. Окончательная структура объекта на панели иерархии должна выглядеть так, как показано на рисунке ниже.

    Снимок экрана: окончательная структура объекта на панели иерархии.

Глава 5. Создание класса MeetingsUI

Первый скрипт, который необходимо создать, — Это MeetingsUI, который отвечает за размещение и заполнение пользовательского интерфейса приложения (приветственное сообщение, инструкции и сведения о собраниях).

Чтобы создать этот класс, выполните указанные ниже действия.

  1. Щелкните правой кнопкой мыши папку Assets на панели проекта и выберите Создать>папку. Назовите папку Scripts.

    Снимок экрана, на котором показано, где найти папку Assets.Снимок экрана, на котором показано, где создать папку Scripts.

  2. Откройте папку Скрипты , а затем щелкните правой кнопкой мыши создать>скрипт C#. Назовите скрипт MeetingsUI.

    Снимок экрана, на котором показано, где создать папку MeetingsUI.

  3. Дважды щелкните новый скрипт MeetingsUI , чтобы открыть его в Visual Studio.

  4. Вставьте следующие пространства имен:

    using System;
    using UnityEngine;
    
  5. Внутри класса вставьте следующие переменные:

        /// <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. Затем замените метод Start() и добавьте метод Awake(). Они будут вызываться при инициализации класса:

        /// <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. Добавьте методы, отвечающие за создание пользовательского интерфейса собраний , и заполните его текущими собраниями по запросу:

        /// <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. Удалите метод Update() и сохраните изменения в Visual Studio, прежде чем вернуться в Unity.

Глава 6. Создание класса Graph

Следующий скрипт, который нужно создать, — это скрипт Graph . Этот скрипт отвечает за выполнение вызовов для проверки подлинности пользователя и получения запланированных собраний на текущий день из календаря пользователя.

Чтобы создать этот класс, выполните указанные ниже действия.

  1. Дважды щелкните папку Скрипты , чтобы открыть ее.

  2. Щелкните правой кнопкой мыши в папке Скрипты и выберите Создать>скрипт C#. Присвойте скрипту имя Graph.

  3. Дважды щелкните скрипт, чтобы открыть его в Visual Studio.

  4. Вставьте следующие пространства имен:

    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
    

    Важно!

    Вы заметите, что части кода в этом скрипте заключены в оболочку с директивами precompile, чтобы избежать проблем с библиотеками при сборке решения Visual Studio.

  5. Удалите методы Start() и Update(), так как они не будут использоваться.

  6. Вне класса Graph вставьте следующие объекты, необходимые для десериализации объекта JSON, представляющего ежедневные запланированные собрания:

    /// <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. В классе Graph добавьте следующие переменные:

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

    Примечание

    Измените значение appId на идентификатор приложения , который вы записали в главе 1, шаг 4. Это значение должно совпадать с значением, отображаемым на портале регистрации приложений на странице регистрации приложения.

  8. В классе Graph добавьте методы SignInAsync() и AquireTokenAsync(), которые будут предлагать пользователю вставить учетные данные для входа.

        /// <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. Добавьте следующие два метода:

    1. BuildTodayCalendarEndpoint(), который создает универсальный код ресурса (URI), указывающий день и интервал времени, в течение которого извлекаются запланированные собрания.

    2. ListMeetingsAsync(), запрашивающий запланированные собрания из Microsoft 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. Вы завершили скрипт Graph . Сохраните изменения в Visual Studio перед возвращением в Unity.

Глава 7. Создание скрипта GazeInput

Теперь вы создадите GazeInput. Этот класс обрабатывает и отслеживает взгляд пользователя, используя Raycast , поступающий от основной камеры, проецируя вперед.

Чтобы создать скрипт, выполните указанные ниже действия.

  1. Дважды щелкните папку Скрипты , чтобы открыть ее.

  2. Щелкните правой кнопкой мыши в папке Скрипты и выберите Создать>скрипт C#. Присвойте скрипту имя GazeInput.

  3. Дважды щелкните скрипт, чтобы открыть его в Visual Studio.

  4. Измените код пространств имен в соответствии с приведенным ниже, а также добавьте тег "[System.Serializable]" над классом GazeInput , чтобы его можно было сериализовать:

    using UnityEngine;
    
    /// <summary>
    /// Class responsible for the User's Gaze interactions
    /// </summary>
    [System.Serializable]
    public class GazeInput : MonoBehaviour
    {
    
  5. В класс GazeInput добавьте следующие переменные:

        [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. Добавьте метод CreateCursor(), чтобы создать курсор HoloLens в сцене, и вызовите метод из метода 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. Следующие методы позволяют осуществлять взгляд Raycast и отслеживать фокусированные объекты.

    /// <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. Сохраните изменения в Visual Studio перед возвращением в Unity.

Глава 8. Создание класса Interactions

Теперь вам потребуется создать скрипт Взаимодействия , который отвечает за:

  • Обработка касания и взгляда камеры, что позволяет пользователю взаимодействовать с кнопкой входа в сцене.

  • Создание объекта button в журнале в сцене для взаимодействия пользователя.

Чтобы создать скрипт, выполните указанные ниже действия.

  1. Дважды щелкните папку Скрипты , чтобы открыть ее.

  2. Щелкните правой кнопкой мыши в папке Скрипты и выберите Создать>скрипт C#. Присвойте скрипту имя Interactions.

  3. Дважды щелкните скрипт, чтобы открыть его в Visual Studio.

  4. Вставьте следующие пространства имен:

    using UnityEngine;
    using UnityEngine.XR.WSA.Input;
    
  5. Измените наследование класса Interaction с MonoBehaviour на GazeInput.

    взаимодействия с открытыми классами: MonoBehaviour

    public class Interactions : GazeInput
    
  6. Внутри класса Interaction вставьте следующую переменную:

        /// <summary>
        /// Allows input recognition with the HoloLens
        /// </summary>
        private GestureRecognizer _gestureRecognizer;
    
  7. Замените метод Start ; обратите внимание, что это метод переопределения, который вызывает метод класса "base" Gaze. Start() будет вызываться при инициализации класса, регистрации для распознавания входных данных и создания кнопки входа в сцене:

        /// <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. Добавьте метод CreateSignInButton(), который создаст экземпляр кнопки входа в сцене и задаст ее свойства:

        /// <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. Добавьте метод GestureRecognizer_Tapped(), который будет отвечать на событие Пользователя Tap .

        /// <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. Удалите метод Update(), а затем сохраните изменения в Visual Studio перед возвращением в Unity.

Глава 9. Настройка ссылок на скрипты

В этой главе необходимо поместить сценарий взаимодействия на главную камеру. Затем этот скрипт будет обрабатывать размещение других скриптов там, где они должны быть.

  • Из папки Scripts (Скрипты ) на панели проекта перетащите скрипт Interactions (Взаимодействия ) в объект Main Camera (Основная камера ), как показано ниже.

    Снимок экрана: место перетаскивания скрипта Взаимодействия.

Глава 10. Настройка тега

Код, обрабатывающий взгляд, будет использовать тег SignInButton , чтобы определить, с каким объектом пользователь будет взаимодействовать для входа в Microsoft Graph.

Чтобы создать тег, выполните следующие действия.

  1. В редакторе Unity щелкните основную камеру на панели иерархии.

  2. На панели инспектора щелкните тегMainCamera, чтобы открыть раскрывающийся список. Щелкните Добавить тег...

    Снимок экрана: добавление тега... Параметр.

  3. Нажмите кнопку +.

    Снимок экрана: кнопка

  4. Запишите имя тега как SignInButton и нажмите кнопку Сохранить.

    Снимок экрана, на котором показано, куда добавить имя тега SignInButton.

Глава 11. Сборка проекта Unity в UWP

Все необходимое для раздела Unity этого проекта завершено, поэтому пришло время создать его из Unity.

  1. Перейдите в раздел Параметры сборки (Параметры сборкифайла>).

    Снимок экрана: диалоговое окно

  2. Если это еще не так, установите флажок Проекты Unity C#.

  3. Щелкните Построить. Unity запустит окно проводник, в котором необходимо создать, а затем выбрать папку для сборки приложения. Создайте папку и назовите ее App. Затем, выбрав папку приложения , щелкните Выбрать папку.

  4. Unity начнет сборку проекта в папке App .

  5. После завершения сборки Unity (это может занять некоторое время), откроется окно проводник в расположении сборки (проверка панели задач, так как она может не всегда отображаться над окнами, но будет уведомлять вас о добавлении нового окна).

Глава 12. Развертывание в HoloLens

Чтобы развернуть в HoloLens, выполните приведенные далее действия.

  1. Вам потребуется IP-адрес HoloLens (для удаленного развертывания) и убедитесь, что HoloLens находится в режиме разработчика. Для этого выполните указанные ниже действия.

    1. При ношении HoloLens откройте раздел Параметры.

    2. Перейдите в раздел Сетевые & ДополнительныепараметрыWi-Fi> в Интернете >

    3. Запишите IPv4-адрес .

    4. Затем вернитесь к разделу Параметры, а затем выберите Обновление безопасности &>для разработчиков.

    5. Установите режим разработчика включено.

  2. Перейдите к новой сборке Unity (папке App ) и откройте файл решения в Visual Studio.

  3. В разделе Конфигурация решения выберите Отладка.

  4. В разделе Платформа решения выберите x86, Удаленный компьютер. Вам будет предложено вставить IP-адрес удаленного устройства (в данном случае — HoloLens, который вы записали).

    Снимок экрана, на котором показано, где выбрать x86 и удаленный компьютер.

  5. Перейдите в меню Сборка и щелкните Развернуть решение , чтобы загрузить неопубликованное приложение в HoloLens.

  6. Теперь ваше приложение должно появиться в списке установленных на HoloLens приложений, готовых к запуску!

Приложение Microsoft Graph HoloLens

Поздравляем! Вы создали приложение смешанной реальности, которое использует Microsoft Graph для чтения и отображения данных календаря пользователя.

Снимок экрана: готовое приложение смешанной реальности.

Дополнительные упражнения

Упражнение 1.

Использование Microsoft Graph для отображения других сведений о пользователе

  • Адрес электронной почты пользователя, номер телефона, изображение профиля

Упражнение 1.

Реализуйте голосовое управление для навигации по пользовательскому интерфейсу Microsoft Graph.