311. Смешанная реальность и Azure — Microsoft GraphMR and Azure 311 - Microsoft Graph

Примечание

Руководства Mixed Reality Academy были разработаны для иммерсивных гарнитур HoloLens (1-го поколения) и иммерсивных гарнитур Mixed Reality.The Mixed Reality Academy tutorials were designed with HoloLens (1st gen) and Mixed Reality Immersive Headsets in mind. Поэтому мы считаем, что важно оставить эти руководства для разработчиков, которые ищут рекомендации по разработке для этих устройств.As such, we feel it is important to leave these tutorials in place for developers who are still looking for guidance in developing for those devices. Данные руководства не будут обновляться с учетом последних наборов инструментов или возможностей взаимодействия для HoloLens 2.These tutorials will not be updated with the latest toolsets or interactions being used for HoloLens 2. Они будут сохранены для работы на поддерживаемых устройствах.They will be maintained to continue working on the supported devices. Появится новая серия руководств, которые будут опубликованы в будущем, где будет показано, как разрабатывать данные для HoloLens 2.There will be a new series of tutorials that will be posted in the future that will demonstrate how to develop for HoloLens 2. Это уведомление будет обновлено ссылкой на эти учебники при их публикации.This notice will be updated with a link to those tutorials when they are posted.

В этом курсе вы узнаете, как использовать Microsoft Graph для входа в учетная запись Майкрософт с помощью безопасной проверки подлинности в приложении смешанной реальности.In this course, you will learn how to use Microsoft Graph to log in into your Microsoft account using secure authentication within a mixed reality application. Затем вы получите и отобразите запланированные собрания в интерфейсе приложения.You will then retrieve and display your scheduled meetings in the application interface.

Microsoft Graph — это набор интерфейсов API, предназначенных для обеспечения доступа ко многим службам Майкрософт.Microsoft Graph is a set of APIs designed to enable access to many of Microsoft's services. Корпорация Майкрософт описывает Microsoft Graph как матрица ресурсов, Соединенных связями, то есть позволяет приложению получать доступ ко всем данным о подключенных пользователях.Microsoft describes Microsoft Graph as being a matrix of resources connected by relationships, meaning it allows an application to access all sorts of connected user data. Дополнительные сведения см. на странице Microsoft Graph.For more information, visit the Microsoft Graph page.

Разработка будет включать в себя создание приложения, в котором пользователю будет предложено Взгляните на сферу, а затем коснуться сферы, которая предложит пользователю безопасно войти в учетная запись Майкрософт.Development will include the creation of an app where the user will be instructed to gaze at and then tap a sphere, which will prompt the user to log in safely to a Microsoft account. После входа в учетную запись пользователь увидит список собраний, запланированных на данный день.Once logged in to their account, the user will be able to see a list of meetings scheduled for the day.

Прополнив этот курс, вы получите приложение HoloLens для смешанной реальности, которое сможет сделать следующее:Having completed this course, you will have a mixed reality HoloLens application, which will be able to do the following:

  1. С помощью жеста TAP Коснитесь объекта, который предложит пользователю войти в учетную запись Майкрософт (выход из приложения для входа в систему, а затем снова вернуться в приложение).Using the Tap gesture, tap on an object, which will prompt the user to log into a Microsoft Account (moving out of the app to log in, and then back into the app again).
  2. Просмотр списка собраний, запланированных на данный день.View a list of meetings scheduled for the day.

В приложении вы будете выполнять интеграцию результатов с вашей структурой.In your application, it is up to you as to how you will integrate the results with your design. Этот курс предназначен для изучения того, как интегрировать службу Azure с проектом Unity.This course is designed to teach you how to integrate an Azure Service with your Unity project. Это ваша задача использовать знания, полученные из этого курса, для улучшения приложения смешанной реальности.It is your job to use the knowledge you gain from this course to enhance your mixed reality application.

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

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

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

Примечание

Этот учебник предназначен для разработчиков, имеющих базовый опыт работы с Unity и C#.This tutorial is designed for developers who have basic experience with Unity and C#. Также имейте в виду, что предварительные требования и письменные инструкции в этом документе отражают, что проверялось и проверено на момент написания статьи (Июль 2018).Please also be aware that the prerequisites and written instructions within this document represent what has been tested and verified at the time of writing (July 2018). Вы можете использовать новейшее программное обеспечение, как указано в статье Установка средств , но не следует предполагать, что информация в этом курсе будет полностью соответствовать тому, что вы найдете в более новом программном обеспечении, чем указано ниже.You are free to use the latest software, as listed within the install the tools article, though it should not be assumed that the information in this course will perfectly match what you will find in newer software than what is listed below.

Для этого курса рекомендуется следующее оборудование и программное обеспечение:We recommend the following hardware and software for this course:

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

  1. Чтобы избежать проблем при создании этого проекта, настоятельно рекомендуется создать проект, упомянутый в этом руководстве, в корневой или ближайшем к корневой папке (длинные пути к папкам могут вызвать проблемы во время сборки).To avoid encountering issues building this project, it is strongly suggested that you create the project mentioned in this tutorial in a root or near-root folder (long folder paths can cause issues at build-time).
  2. Настройка и тестирование HoloLens.Set up and test your HoloLens. Если вам нужна поддержка по настройке HoloLens, обязательно посетите статью Настройка hololens.If you need support setting up your HoloLens, make sure to visit the HoloLens setup article.
  3. Рекомендуется выполнять настройку калибровки и датчика при разработке нового приложения HoloLens (иногда это может помочь в выполнении этих задач для каждого пользователя).It is a good idea to perform Calibration and Sensor Tuning when beginning developing a new HoloLens App (sometimes it can help to perform those tasks for each user).

Чтобы получить справку по калибровке, перейдите по этой ссылке в статью калибровка HoloLens.For help on Calibration, please follow this link to the HoloLens Calibration article.

Чтобы получить справку по настройке датчика, перейдите по ссылке в статью Настройка датчика HoloLens.For help on Sensor Tuning, please follow this link to the HoloLens Sensor Tuning article.

Глава 1. Создание приложения на портале регистрации приложенийChapter 1 - Create your app in the Application Registration Portal

Для начала вам потребуется создать и зарегистрировать приложение на портале регистрации приложений.To begin with, you will need to create and register your application in the Application Registration Portal.

В этой главе вы также найдете ключ службы, который позволит выполнять вызовы Microsoft Graph для доступа к содержимому вашей учетной записи.In this Chapter you will also find the Service Key that will allow you to make calls to Microsoft Graph to access your account content.

  1. Перейдите на портал регистрации приложений Майкрософт и войдите с помощью учетной записи Майкрософт.Navigate to the Microsoft Application Registration Portal and login with your Microsoft Account. После входа вы будете перенаправлены на портал регистрации приложений.Once you have logged in, you will be redirected to the Application Registration Portal.

  2. В разделе Мои приложения нажмите кнопку Добавить приложение.In the My applications section, click on the button Add an app.

    Важно!

    Портал регистрации приложений может выглядеть по-разному в зависимости от того, работал ли ранее Microsoft Graph.The Application Registration Portal can look different, depending on whether you have previously worked with Microsoft Graph. На следующих снимках экрана показаны эти различные версии.The below screenshots display these different versions.

  3. Добавьте имя приложения и нажмите кнопку создать.Add a name for your application and click Create.

  4. После создания приложения вы будете перенаправлены на главную страницу приложения.Once the application has been created, you will be redirected to the application main page. Скопируйте идентификатор приложения и запишите это значение в безопасном месте, вы будете использовать его вскоре в своем коде.Copy the Application Id and make sure to note this value somewhere safe, you will use it soon in your code.

  5. В разделе платформы убедитесь, что отображается собственное приложение .In the Platforms section, make sure Native Application is displayed. Если не щелкнуть Добавить платформу и выбрать собственное приложение.If not click on Add Platform and select Native Application.

  6. Прокрутите вниз на той же странице и в разделе, который называется Microsoft Graph разрешениями , необходимо добавить дополнительные разрешения для приложения.Scroll down in the same page and in the section called Microsoft Graph Permissions you will need to add additional permissions for the application. Щелкните Добавить рядом с делегированными разрешениями.Click on Add next to Delegated Permissions.

  7. Так как вы хотите, чтобы приложение поменяло доступ к календарю пользователя, установите флажок календари. чтение и нажмите кнопку ОК.Since you want your application to access the user's Calendar, check the box called Calendars.Read and click OK.

  8. Прокрутите вниз и нажмите кнопку сохранить .Scroll to the bottom and click the Save button.

  9. Сохранение будет подтверждено, и вы можете выйти из портала регистрации приложений.Your save will be confirmed, and you can log out from the Application Registration Portal.

Глава 2. Настройка проекта UnityChapter 2 - Set up the Unity project

Ниже приведена типичная Настройка для разработки с использованием смешанной реальности, которая является хорошим шаблоном для других проектов.The following is a typical set up for developing with mixed reality, and as such, is a good template for other projects.

  1. Откройте Unity и нажмите кнопку создать.Open Unity and click New.

  2. Необходимо указать имя проекта Unity.You need to provide a Unity project name. Вставьте мсграфмр.Insert MSGraphMR. Убедитесь, что для шаблона проекта задано значение 3D.Make sure the project template is set to 3D. Задайте для расположения нужное расположение (Помните, что ближе к корневым каталогам лучше).Set the Location to somewhere appropriate for you (remember, closer to root directories is better). Затем нажмите кнопку создать проект.Then, click Create project.

  3. При открытом Unity стоит проверить, что для редактора скриптов по умолчанию задано значение Visual Studio.With Unity open, it is worth checking the default Script Editor is set to Visual Studio. Перейдите к разделу изменение > настроек , а затем в новом окне перейдите к разделу Внешние инструменты.Go to Edit > Preferences and then from the new window, navigate to External Tools. Измените Редактор внешних скриптов на Visual Studio 2017.Change External Script Editor to Visual Studio 2017. Закройте окно настройки .Close the Preferences window.

  4. Перейдите в раздел > параметры сборки файлов и выберите универсальная платформа Windows, а затем нажмите кнопку переключения платформы , чтобы применить выбранные элементы.Go to File > Build Settings and select Universal Windows Platform, then click on the Switch Platform button to apply your selection.

  5. Несмотря на то , что все еще находятся в > параметрах сборки файлов, убедитесь, что:While still in File > Build Settings, make sure that:

    1. Целевое устройство имеет значение HoloLensTarget Device is set to HoloLens

    2. Для типа сборки задано значение D3DBuild Type is set to D3D

    3. Пакет SDK установлен в значение " Последняя установка "SDK is set to Latest installed

    4. Для версии Visual Studio установлено значение " Последняя установка "Visual Studio Version is set to Latest installed

    5. Сборка и запуск настроены на локальный компьютерBuild and Run is set to Local Machine

    6. Сохраните сцену и добавьте ее в сборку.Save the scene and add it to the build.

      1. Для этого выберите Добавить открытые сцены.Do this by selecting Add Open Scenes. Появится окно сохранения.A save window will appear.

      2. Создайте новую папку для этой и любой будущей сцены.Create a new folder for this, and any future, scene. Нажмите кнопку создать папку , чтобы создать новую папку, назовите ее « сцены».Select the New folder button, to create a new folder, name it Scenes.

      3. Откройте только что созданную папку сцены , а затем в поле имя файла: введите MR_ComputerVisionScene, а затем нажмите кнопку сохранить.Open your newly created Scenes folder, and then in the File name: text field, type MR_ComputerVisionScene, then click Save.

        Важно!

        Помните, что сцены Unity необходимо сохранять в папке Assets , так как они должны быть связаны с проектом Unity.Be aware, you must save your Unity scenes within the Assets folder, as they must be associated with the Unity project. Создание папки «сцены» (и других аналогичных папок) — типичный способ структуризации проекта Unity.Creating the scenes folder (and other similar folders) is a typical way of structuring a Unity project.

    7. Оставшиеся параметры, в параметрах сборки, должны быть оставлены по умолчанию.The remaining settings, in Build Settings, should be left as default for now.

  6. В окне параметры сборки нажмите кнопку Параметры проигрывателя , чтобы открыть связанную панель в пространстве, где находится инспектор .In the Build Settings window, click on the Player Settings button, this will open the related panel in the space where the Inspector is located.

  7. На этой панели необходимо проверить несколько параметров:In this panel, a few settings need to be verified:

    1. На вкладке другие параметры выполните следующие действия.In the Other Settings tab:

      1. Версия среды выполнения сценариев должна быть экспериментальной (эквивалент .NET 4,6), что вызовет необходимость перезапуска редактора.Scripting Runtime Version should be Experimental (.NET 4.6 Equivalent), which will trigger a need to restart the Editor.

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

      3. Уровень совместимости API должен быть .NET 4,6API Compatibility Level should be .NET 4.6

    2. На вкладке Параметры публикации в разделе возможности установите флажок:Within the Publishing Settings tab, under Capabilities, check:

      • InternetClient;InternetClient

    3. На более низких панели в параметрах XR (см. ниже Параметры публикации) Проверьте, поддерживается ли пакет SDK для Windows Mixed Reality .Further down the panel, in XR Settings (found below Publish Settings), check Virtual Reality Supported, make sure the Windows Mixed Reality SDK is added.

  8. Вернемся к параметрам сборки. проекты C# для Unity больше не заключаются; Установите флажок рядом с этим.Back in Build Settings, Unity C# Projects is no longer greyed out; check the checkbox next to this.

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

  10. Сохраните сцену и проект (файл > сохранить сцены/файл > сохранить проект).Save your scene and project (FILE > SAVE SCENES / FILE > SAVE PROJECT).

Глава 3. импорт библиотек в UnityChapter 3 - Import Libraries in Unity

Важно!

Если вы хотите пропустить компонент установки Unity, установленный в этом курсе, и продолжить работу с кодом, скачайте этот Azure-MR-311. пакет unitypackage, импортируйте его в проект в качестве пользовательского пакета, а затем продолжайте в главе 5.If you wish to skip the Unity Set up component of this course, and continue straight into code, feel free to download this Azure-MR-311.unitypackage, import it into your project as a Custom Package, and then continue from Chapter 5.

Чтобы использовать Microsoft Graph в Unity, необходимо использовать библиотеку DLL Microsoft. Identity. Client .To use Microsoft Graph within Unity you need to make use of the Microsoft.Identity.Client DLL. Можно использовать пакет SDK для Microsoft Graph, однако после сборки проекта Unity потребуется добавить пакет NuGet (то есть редактирует проект после сборки).It is possible to use the Microsoft Graph SDK, however, it will require the addition of a NuGet package after you build the Unity project (meaning editing the project post-build). Проще импортировать необходимые библиотеки DLL непосредственно в Unity.It is considered simpler to import the required DLLs directly into Unity.

Примечание

В Unity существует известная ошибка, которая требует перенастройки подключаемых модулей после импорта.There is currently a known issue in Unity which requires plugins to be reconfigured after import. Эти действия (4-7 в этом разделе) больше не понадобятся после устранения ошибки.These steps (4 - 7 in this section) will no longer be required after the bug has been resolved.

Чтобы импортировать Microsoft Graph в свой проект, скачайте файл MSGraph_LabPlugins.zip.To import Microsoft Graph into your own project, download the MSGraph_LabPlugins.zip file. Этот пакет был создан с использованием версий библиотек, которые были проверены.This package has been created with versions of the libraries that have been tested.

Если вы хотите узнать больше о том, как добавить пользовательские библиотеки DLL в проект Unity, перейдите по этой ссылке.If you wish to know more about how to add custom DLLs to your Unity project, follow this link.

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

  1. Добавьте пакет Unity в Unity с помощью команды > > меню настраиваемый пакет импорт активов.Add the Unity Package to Unity by using the Assets > Import Package > Custom Package menu option. Выберите только что скачанный пакет.Select the package you just downloaded.

  2. В появившемся окне Импорт пакета Unity убедитесь, что выбраны все компоненты подключаемых модулей (включая).In the Import Unity Package box that pops up, ensure everything under (and including) Plugins is selected.

  3. Нажмите кнопку Импорт , чтобы добавить элементы в проект.Click the Import button to add the items to your project.

  4. Перейдите в папку мсграф в разделе подключаемые модули на панели проект и выберите подключаемый модуль Microsoft. Identity. Client.Go to the MSGraph folder under Plugins in the Project Panel and select the plugin called Microsoft.Identity.Client.

  5. Выбрав подключаемый модуль , убедитесь, что все платформы не установлены, убедитесь, что флажок всаплайер также не установлен, а затем нажмите кнопку Применить.With the plugin selected, ensure that Any Platform is unchecked, then ensure that WSAPlayer is also unchecked, then click Apply. Это необходимо только для того, чтобы убедиться, что файлы настроены правильно.This is just to confirm that the files are configured correctly.

    Примечание

    Пометка этих подключаемых модулей настраивает их для использования только в редакторе Unity.Marking these plugins configures them to only be used in the Unity Editor. В папке WSA имеется другой набор библиотек DLL, который будет использоваться после экспорта проекта из Unity в качестве универсального приложения Windows.There are a different set of DLLs in the WSA folder which will be used after the project is exported from Unity as a Universal Windows Application.

  6. Далее необходимо открыть папку WSA в папке мсграфNext, you need to open the WSA folder, within the MSGraph folder. Вы увидите копию того же файла, который вы только что настроили.You will see a copy of the same file you just configured. Выберите файл, а затем в инспекторе:Select the file, and then in the inspector:

    • Убедитесь, что все платформы не установлены и установлен флажок только всаплайер .ensure that Any Platform is unchecked, and that only WSAPlayer is checked.

    • Убедитесь, что пакет SDK имеет значение UWP, а для серверной части скрипта задано значение net .Ensure SDK is set to UWP, and Scripting Backend is set to Dot Net

    • Убедитесь, что флажок не обрабатывать установлен.Ensure that Don't process is checked.

  7. Нажмите кнопку Применить.Click Apply.

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

В этой главе вы настроите основную камеру для сцены:During this Chapter you will set up the Main Camera of your scene:

  1. На панели Иерархия выберите основную камеру.In the Hierarchy Panel, select the Main Camera.

  2. После выбора вы сможете увидеть все компоненты основной камеры на панели инспектора .Once selected, you will be able to see all the components of the Main Camera in the Inspector panel.

    1. Объект Camera должен называться основной камерой (Обратите внимание на орфографию!)The Camera object must be named Main Camera (note the spelling!)

    2. Для тега основной камеры необходимо задать значение маинкамера (Обратите внимание на правописание).The Main Camera Tag must be set to MainCamera (note the spelling!)

    3. Убедитесь, что для параметра Расположение преобразования задано значение 0, 0, 0 .Make sure the Transform Position is set to 0, 0, 0

    4. Установить для чистых флагов сплошной цветSet Clear Flags to Solid Color

    5. Установить черный цвет фона для компонента камеры , альфа 0 (шестнадцатеричный код: #00000000)Set the Background Color of the Camera Component to Black, Alpha 0 (Hex Code: #00000000)

  3. Итоговая структура объектов на панели Иерархия должна выглядеть так, как показано на рисунке ниже:The final object structure in the Hierarchy Panel should be like the one shown in the image below:

Глава 5. Создание класса МитингсуиChapter 5 - Create MeetingsUI class

Первый сценарий, который необходимо создать, — это митингсуи, который отвечает за размещение и заполнение пользовательского интерфейса приложения (приветственное сообщение, инструкции и сведения о собраниях).The first script you need to create is MeetingsUI, which is responsible for hosting and populating the UI of the application (welcome message, instructions and the meetings details).

Чтобы создать этот класс, сделайте следующее:To create this class:

  1. Щелкните правой кнопкой мыши папку Assets на панели проект, а затем выберите создать > папку.Right-click on the Assets folder in the Project Panel, then select Create > Folder. Назовите папку Scripts.Name the folder Scripts.

  2. Откройте папку Scripts , а затем в этой папке щелкните правой кнопкой мыши и в контекстном меню выберите создать > скрипт C#.Open the Scripts folder then, within that folder, right-click, Create > C# Script. Назовите сценарий митингсуи.Name the script MeetingsUI.

  3. Дважды щелкните новый скрипт митингсуи , чтобы открыть его в Visual Studio.Double-click on the new MeetingsUI script to open it with Visual Studio.

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

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

        /// <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 () и добавьте метод спящего режима () .Then replace the Start() method and add an Awake() method. Они будут вызываться при инициализации класса:These will be called when the class initializes:

        /// <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. Добавьте методы, отвечающие за создание пользовательского интерфейса совещаний , и заполните его текущими собраниями по запросу:Add the methods responsible for creating the Meetings UI and populate it with the current meetings when requested:

        /// <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.Delete the Update() method, and save your changes in Visual Studio before returning to Unity.

Глава 6. Создание класса GraphChapter 6 - Create the Graph class

Следующий скрипт для создания — это сценарий графа .The next script to create is the Graph script. Этот сценарий отвечает за выполнение вызовов для проверки подлинности пользователя и получение запланированных собраний за текущий день из календаря пользователя.This script is responsible for making the calls to authenticate the user and retrieve the scheduled meetings for the current day from the user's calendar.

Чтобы создать этот класс, сделайте следующее:To create this class:

  1. Дважды щелкните папку Scripts , чтобы открыть ее.Double-click on the Scripts folder, to open it.

  2. Щелкните правой кнопкой мыши внутри папки Scripts и выберите пункт создать > скрипт C#.Right-click inside the Scripts folder, click Create > C# Script. Присвойте имя графу скрипта.Name the script Graph.

  3. Дважды щелкните скрипт, чтобы открыть его в Visual Studio.Double-click on the script to open it with Visual Studio.

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

    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
    

    Важно!

    Обратите внимание, что части кода в этом скрипте заключены в оболочку для директив предварительной компиляции. Это позволяет избежать проблем с библиотеками при построении решения Visual Studio.You will notice that parts of the code in this script are wrapped around Precompile Directives, this is to avoid issues with the libraries when building the Visual Studio Solution.

  5. Удалите методы Start () и Update () , так как они не будут использоваться.Delete the Start() and Update() methods, as they will not be used.

  6. За пределами класса Graph вставьте следующие объекты, которые необходимы для десериализации объекта JSON, представляющего ежедневные запланированные собрания:Outside the Graph class, insert the following objects, which are necessary to deserialize the JSON object representing the daily scheduled meetings:

    /// <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 добавьте следующие переменные:Inside the Graph class, add the following variables:

        /// <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.Change the appId value to be the App Id that you have noted in Chapter 1, step 4. Это значение должно совпадать со значением, отображаемым на портале регистрации приложений на странице регистрации приложения.This value should be the same as that displayed in the Application Registration Portal, in your application registration page.

  8. В классе Graph добавьте методы сигнинасинк () и акуиретокенасинк (), которые предложит пользователю вставить учетные данные для входа.Within the Graph class, add the methods SignInAsync() and AquireTokenAsync(), that will prompt the user to insert the log-in credentials.

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

    1. Буилдтодайкалендарендпоинт (), который создает URI, указывающий день, и интервал времени, в который извлекаются запланированные собрания.BuildTodayCalendarEndpoint(), which builds the URI specifying the day, and time span, in which the scheduled meetings are retrieved.

    2. Листмитингсасинк (), которая запрашивает запланированные собрания Microsoft Graph.ListMeetingsAsync(), which requests the scheduled meetings from 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 .You have now completed the Graph script. Сохраните изменения в Visual Studio перед возвратом в Unity.Save your changes in Visual Studio before returning to Unity.

Глава 7. Создание скрипта ГазеинпутChapter 7 - Create the GazeInput script

Теперь создадим газеинпут.You will now create the GazeInput. Этот класс обрабатывает и отслеживает взгляд пользователя, используя райкаст , поступающий от основной камеры, проецирование вперед.This class handles and keeps track of the user's gaze, using a Raycast coming from the Main Camera, projecting forward.

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

  1. Дважды щелкните папку Scripts , чтобы открыть ее.Double-click on the Scripts folder, to open it.

  2. Щелкните правой кнопкой мыши внутри папки Scripts и выберите пункт создать > скрипт C#.Right-click inside the Scripts folder, click Create > C# Script. Назовите сценарий газеинпут.Name the script GazeInput.

  3. Дважды щелкните скрипт, чтобы открыть его в Visual Studio.Double-click on the script to open it with Visual Studio.

  4. Измените код пространства имен, чтобы он соответствовал приведенному ниже, вместе с добавлением тега [ System. ] Serializable над классом газеинпут , чтобы его можно было сериализовать:Change the namespaces code to match the one below, along with adding the '[System.Serializable]' tag above your GazeInput class, so that it can be serialized:

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

        [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. Добавьте метод креатекурсор () , чтобы создать курсор HoloLens в сцене, и вызовите метод из метода Start () :Add the CreateCursor() method to create the HoloLens cursor in the scene, and call the method from the Start() method:

        /// <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. Следующие методы позволяют Райкасту взгляда и отслеживание объектов с сортировкой.The following methods enable the gaze Raycast and keep track of the focused objects.

    /// <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.Save your changes in Visual Studio before returning to Unity.

Глава 8. Создание класса взаимодействийChapter 8 - Create the Interactions class

Теперь потребуется создать скрипт взаимодействия , который отвечает за:You will now need to create the Interactions script, which is responsible for:

  • Обработка взаимодействия касания и обзора камеры, которая позволяет пользователю взаимодействовать с журналом "Кнопка" в сцене.Handling the Tap interaction and the Camera Gaze, which enables the user to interact with the log in "button" in the scene.

  • Создание входного объекта "Кнопка" в сцене для пользователя, с которым будет взаимодействовать.Creating the log in "button" object in the scene for the user to interact with.

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

  1. Дважды щелкните папку Scripts , чтобы открыть ее.Double-click on the Scripts folder, to open it.

  2. Щелкните правой кнопкой мыши внутри папки Scripts и выберите пункт создать > скрипт C#.Right-click inside the Scripts folder, click Create > C# Script. Назовите скрипт взаимодействия.Name the script Interactions.

  3. Дважды щелкните скрипт, чтобы открыть его в Visual Studio.Double-click on the script to open it with Visual Studio.

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

    using UnityEngine;
    using UnityEngine.XR.WSA.Input;
    
  5. Измените наследование класса взаимодействия , используя неизменное поведение , на газеинпут.Change the inheritance of the Interaction class from MonoBehaviour to GazeInput.

    Взаимодействие открытых классов: одновариантное поведениеpublic class Interactions : MonoBehaviour

    public class Interactions : GazeInput
    
  6. Внутри класса взаимодействия вставьте следующую переменную:Inside the Interaction class insert the following variable:

        /// <summary>
        /// Allows input recognition with the HoloLens
        /// </summary>
        private GestureRecognizer _gestureRecognizer;
    
  7. Замените метод Start ; Обратите внимание, что это метод переопределения, который вызывает метод класса взгляда Base.Replace the Start method; notice it is an override method, which calls the 'base' Gaze class method. Start () будет вызываться при инициализации класса, регистрации для распознавания ввода и создании кнопки входа в сцене:Start() will be called when the class initializes, registering for input recognition and creating the sign in button in the scene:

        /// <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. Добавьте метод креатесигнинбуттон () , который создаст экземпляр кнопки входа в сцене и установит его свойства:Add the CreateSignInButton() method, which will instantiate the sign in button in the scene and set its properties:

        /// <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 пользователь.Add the GestureRecognizer_Tapped() method, which be respond for the Tap user event.

        /// <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.Delete the Update() method, and then save your changes in Visual Studio before returning to Unity.

Глава 9. Настройка ссылок на скриптыChapter 9 - Set up the script references

В этой главе необходимо разместить сценарий взаимодействия на основной камере.In this Chapter you need to place the Interactions script onto the Main Camera. Затем этот скрипт будет обрабатывать размещение других сценариев, где они должны быть.That script will then handle placing the other scripts where they need to be.

  • В папке скрипты на панели проект перетащите диалоговые окна взаимодействия сценария в основной объект Camera , как показано на рисунке ниже.From the Scripts folder in the Project Panel, drag the script Interactions to the Main Camera object, as pictured below.

Глава 10. Настройка тегаChapter 10 - Setting up the Tag

Код, обрабатывающий взгляд, будет использовать тег сигнинбуттон для указания объекта, с которым пользователь будет взаимодействовать для входа в Microsoft Graph.The code handling the gaze will make use of the Tag SignInButton to identify which object the user will interact with to sign-in to Microsoft Graph.

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

  1. В редакторе Unity щелкните главную камеру на панели Иерархия.In the Unity Editor click on the Main Camera in the Hierarchy Panel.

  2. На панели инспектора щелкните тег маинкамера , чтобы открыть раскрывающийся список.In the Inspector Panel click on the MainCamera Tag to open a drop-down list. Щелкните Добавить тег...Click on Add Tag...

  3. Нажмите кнопку + .Click on the + button.

  4. Запишите имя тега как сигнинбуттон и нажмите кнопку Сохранить.Write the Tag name as SignInButton and click Save.

Глава 11. Создание проекта Unity для UWPChapter 11 - Build the Unity project to UWP

Все необходимое для раздела Unity этого проекта теперь завершено, поэтому пришло время создать его из Unity.Everything needed for the Unity section of this project has now been completed, so it is time to build it from Unity.

  1. Перейдите к параметрам сборки (*файл > * параметры сборки * *).Navigate to Build Settings (*File > *Build Settings**).

  2. Если это еще не так, то тактовые # проекты Unity на C.If not already, tick Unity C# Projects.

  3. Щелкните Построить.Click Build. Unity запустит окно проводника , в котором необходимо создать, а затем выбрать папку для сборки приложения.Unity will launch a File Explorer window, where you need to create and then select a folder to build the app into. Создайте эту папку сейчас и назовите ее app Name.Create that folder now, and name it App. Затем выберите папку приложения и щелкните выбрать папку.Then with the App folder selected, click Select Folder.

  4. Unity начнет сборку проекта в папку приложения .Unity will begin building your project to the App folder.

  5. После того как Unity завершит сборку (может занять некоторое время), он откроет окно проводника в расположении сборки (проверьте панель задач, так как она может не всегда отображаться над окнами, но будет уведомлять о добавлении нового окна).Once Unity has finished building (it might take some time), it will open a File Explorer window at the location of your build (check your task bar, as it may not always appear above your windows, but will notify you of the addition of a new window).

Глава 12. Развертывание в HoloLensChapter 12 - Deploy to HoloLens

Для развертывания на HoloLens выполните следующие действия.To deploy on HoloLens:

  1. Вам потребуется IP-адрес HoloLens (для удаленного развертывания) и убедитесь, что HoloLens находится в режиме разработчика.You will need the IP Address of your HoloLens (for Remote Deploy), and to ensure your HoloLens is in Developer Mode. Выполните указанные ниже действия.To do this:

    1. Людьми HoloLens, откройте Параметры.Whilst wearing your HoloLens, open the Settings.

    2. Выберите Сетевые & > > Дополнительные параметры сети Интернет Wi-FiGo to Network & Internet > Wi-Fi > Advanced Options

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

    4. Затем вернитесь к параметрам и Обновите & безопасности > для разработчиков .Next, navigate back to Settings, and then to Update & Security > For Developers

    5. Задайте режим разработчика на.Set Developer Mode On.

  2. Перейдите к новой сборке Unity (папка приложения ) и откройте файл решения в Visual Studio.Navigate to your new Unity build (the App folder) and open the solution file with Visual Studio.

  3. В конфигурации решения выберите Отладка.In the Solution Configuration select Debug.

  4. На платформе решения выберите x86, удаленный компьютер.In the Solution Platform, select x86, Remote Machine. Вам будет предложено вставить IP-адрес удаленного устройства (в данном случае это HoloLens).You will be prompted to insert the IP address of a remote device (the HoloLens, in this case, which you noted).

  5. Перейдите в меню Сборка и щелкните Развернуть решение , чтобы загружать неопубликованные приложение в HoloLens.Go to Build menu and click on Deploy Solution to sideload the application to your HoloLens.

  6. Теперь приложение должно отобразиться в списке установленных приложений в HoloLens, готовом к запуску.Your app should now appear in the list of installed apps on your HoloLens, ready to be launched!

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

Поздравляем, вы создали приложение смешанной реальности, которое использует Microsoft Graph для чтения и просмотра данных календаря пользователя.Congratulations, you built a mixed reality app that leverages the Microsoft Graph, to read and display user Calendar data.

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

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

Использование Microsoft Graph для просмотра других сведений о пользователеUse Microsoft Graph to display other information about the user

  • Адрес электронной почты пользователя, номер телефона или изображение профиляUser email / phone number / profile picture

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

Реализуйте голосовое управление для навигации по Microsoft Graph пользовательскому интерфейсу.Implement voice control to navigate the Microsoft Graph UI.