HoloLens (1 gen) и Azure 305: функции и хранилище


Примечание

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


final product -start

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

Функции Azure — это служба Майкрософт, которая позволяет разработчикам запускать небольшие фрагменты кода "функции" в Azure. Это позволяет делегировать работу в облако, а не локальное приложение, которое может иметь множество преимуществ. Функции Azure поддерживают несколько языков разработки, включая C#, F #, Node.js, Java и PHP. Дополнительные сведения см. в статье о функциях Azure.

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

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

  1. Позволяет пользователю взходить на сцену.
  2. Активировать порождение объектов, когда пользователь высматривает трехмерную кнопку "Кнопка".
  3. Порожденные объекты будут выбраны функцией Azure.
  4. при порождении каждого объекта приложение сохранит тип объекта в файле Azure, расположенном в служба хранилища Azure.
  5. После второй загрузки данные файла Azure будут получены и использованы для воспроизведения порожденных действий от предыдущего экземпляра приложения.

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

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

Курс HoloLens Иммерсивные гарнитуры
305. Смешанная реальность и Azure: функции и хранилище ✔️ ✔️

Примечание

хотя в этом курсе основное внимание уделяется Windows Mixed Realityным (VR) гарнитурам, вы также можете применить знания, находящиеся в этом курсе, для Microsoft HoloLens. Как вы пройдете вместе с курсом, вы увидите примечания о любых изменениях, которые могут потребоваться для поддержки HoloLens.

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

Примечание

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

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

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

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

Глава 1. портал Azure

чтобы использовать службу служба хранилища Azure, необходимо создать и настроить учетную запись служба хранилища в портал Azure.

  1. Войдите на портал Azure.

    Примечание

    Если у вас еще нет учетной записи Azure, необходимо создать ее. Если вы используете этот учебник в учебной или лабораторной ситуации, обратитесь к своему преподавателю или к одной из прокторс, чтобы получить помощь в настройке новой учетной записи.

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

    azure storage search

    Примечание

    Слово New может быть заменено на создать ресурсв новых порталах.

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

    create service

  4. После нажатия кнопки создать:

    1. Введите имя для своей учетной записи. Имейте в виду, что это поле принимает только цифры и строчные буквы.

    2. В качестве модели развертываниявыберите Resource Manager.

    3. в качестве типа учетной записивыберите служба хранилища (общего назначенияверсии 1).

    4. Определите Расположение группы ресурсов (при создании новой группы ресурсов). В идеале это расположение будет находиться в регионе, в котором будет выполняться приложение. Некоторые ресурсы Azure доступны только в определенных регионах.

    5. Для репликации выберите геоизбыточное хранилище (RA-GRS) с доступом для чтения.

    6. В разделе Производительность выберите Стандартная.

    7. Оставьте защищенное перемещение обязательным , как отключено.

    8. Выберите подписку.

    9. Выберите группу ресурсов или создайте новую. Группа ресурсов предоставляет способ мониторинга, контроля доступа, подготовки счетов и управления ими для коллекции ресурсов Azure. Рекомендуется, чтобы все службы Azure, связанные с одним проектом (например, в этих лабораториях), были в общей группе ресурсов.

      Если вы хотите ознакомиться с дополнительными сведениями о группах ресурсов Azure, обратитесь к статье о группе ресурсов.

    10. Также необходимо подтвердить, что вы поняли условия, примененные к этой службе.

    11. Щелкните Создать.

      input service info

  5. После нажатия кнопки создатьнеобходимо подождать, пока не будет создана служба, а это может занять некоторое время.

  6. После создания экземпляра службы на портале отобразится уведомление.

    new notification in azure portal

  7. Щелкните уведомления, чтобы изучить новый экземпляр службы.

    go to resource

  8. Нажмите кнопку " Переход к ресурсу " в уведомлении, чтобы изучить новый экземпляр службы. вы будете перенаправлены на новый экземпляр службы учетных записей служба хранилища .

    access keys

  9. Щелкните ключи доступа, чтобы отобразить конечные точки для этой облачной службы. чтобы скопировать один из ключей для последующего использования, используйте Блокнот или аналогичные. Кроме того, обратите внимание на значение строки подключения , так как оно будет использоваться в классе азуресервицес , который будет создан позже.

    copy connection string

Глава 2. Настройка функции Azure

Теперь вы можете написать функцию Azure в службе Azure.

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

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

  1. На портале Azureщелкните создать в левом верхнем углу и найдите приложение-функцияи нажмите клавишу Ввод.

    create function app

    Примечание

    Слово New может быть заменено на создать ресурсв новых порталах.

  2. На новой странице будет представлено описание службы приложение-функция Azure . В нижнем левом углу этого запроса нажмите кнопку создать , чтобы создать связь с этой службой.

    function app info

  3. После нажатия кнопки создать:

    1. Укажите имя приложения. Здесь можно использовать только буквы и цифры (допускается использование прописных и строчных букв).

    2. Выберите предпочитаемую подписку.

    3. Выберите группу ресурсов или создайте новую. Группа ресурсов предоставляет способ мониторинга, контроля доступа, подготовки счетов и управления ими для коллекции ресурсов Azure. Рекомендуется, чтобы все службы Azure, связанные с одним проектом (например, в этих лабораториях), были в общей группе ресурсов.

      Если вы хотите ознакомиться с дополнительными сведениями о группах ресурсов Azure, обратитесь к статье о группе ресурсов.

    4. в этом упражнении выберите Windows в качестве выбранной ос.

    5. Выберите план потребления для плана размещения.

    6. Определите Расположение группы ресурсов (при создании новой группы ресурсов). В идеале это расположение будет находиться в регионе, в котором будет выполняться приложение. Некоторые ресурсы Azure доступны только в определенных регионах. Для оптимальной производительности выберите тот же регион, что и для учетной записи хранения.

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

    8. для этого упражнения не выполняйте Application Insights .

      input function app details

  4. Нажмите кнопку Создать .

  5. После нажатия кнопки создатьнеобходимо подождать, пока не будет создана служба, а это может занять некоторое время.

  6. После создания экземпляра службы на портале отобразится уведомление.

    new azure portal notification

  7. Щелкните уведомления, чтобы изучить новый экземпляр службы.

    go to resource function app

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

  9. На панели мониторинга приложение-функция наведите указатель мыши на функции, расположенные на панели слева, а затем щелкните символ + (плюс) .

    create new function

  10. На следующей странице убедитесь, что веб-перехватчик + API выбран, и для выбора языка выберите CSharp, так как это будет язык, используемый в этом руководстве. Наконец, нажмите кнопку создать эту функцию .

    select web hook csharp

  11. Вы должны присутствовать на кодовой странице (Run. CSX), если это не так, щелкните созданную функцию в списке функции на панели слева.

    open new function

  12. Скопируйте следующий код в функцию. Эта функция будет просто возвращать случайное целое число от 0 до 2 при вызове. Не беспокойтесь о существующем коде, вы можете вставить его в верхнюю часть.

        using System.Net;
        using System.Threading.Tasks;
    
        public static int Run(CustomObject req, TraceWriter log)
        {
            Random rnd = new Random();
            int randomInt = rnd.Next(0, 3);
            return randomInt;
        }
    
        public class CustomObject
        {
            public String name {get; set;}
        }
    
  13. Щелкните Сохранить.

  14. Результат должен выглядеть, как показано на рисунке ниже.

  15. Щелкните получить URL-адрес функции и обратите внимание на отображаемую конечную точку . Его необходимо вставить в класс азуресервицес , который будет создан далее в этом курсе.

    Get function endpoint

    Insert function endpoint

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

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

Настройка и тестирование иммерсивного наушников смешанной реальности.

Примечание

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

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

    Create new unity project

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

    Give new unity project a name

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

    set visual studio as script editor

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

    switch platform to uwp

  5. перейдите в Параметры сборки файлов и убедитесь в том, что:

    1. Целевое устройство настроено для любого устройства.

      для Microsoft HoloLens задайте для параметра целевое устройство значение HoloLens.

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

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

    4. для Visual Studio установлена последняя установленнаяверсия

    5. Сборка и запуск настроены на локальный компьютер

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

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

        add open scenes

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

        create scenes folder

      3. Откройте созданную папку сцены , а затем в текстовом поле имя файла введите функтионссцене, а затем нажмите кнопку сохранить.

        Save functions scene

  6. остальные параметры в Параметры сборкидолжны быть оставлены по умолчанию.

    Leave default build settings

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

    player settings in inspector

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

    1. на вкладке другие Параметры :

      1. Версия среды выполнения сценариев должна быть экспериментальной (эквивалент .NET 4,6), что вызовет необходимость перезапуска редактора.
      2. Серверная часть сценариев должна быть .NET
      3. Уровень совместимости API должен быть .NET 4,6
    2. на вкладке публикация Параметры в разделе возможностиустановите флажок:

      • InternetClient;

        set capabilities

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

      set XR settings

  9. назад в сборке Параметрыпроекты C# для Unity больше не выделяются. установите флажок рядом с этим.

    tick c# projects

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

  11. сохраните сцену и Project (файлсохранить сцену/файлсохранить проект).

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

Важно!

Если вы хотите пропустить настройку Unity, настроили компоненты этого курса и продолжить работу с кодом, Скачайте этот файл. пакет unitypackageи импортируйте его в проект как пользовательский пакет. Это также будет содержать библиотеки DLL из следующей главы. После импорта продолжите работу с главой 7.

  1. На панели Иерархиявы найдете объект с названием Главная камера, этот объект представляет "головную точку представления", когда вы "внутри приложения".

  2. На панели мониторинга Unity перед вами выберите основную камеру GameObject. Вы заметите, что на панели инспектора (как правило, на панели мониторинга) отображаются различные компоненты этого GameObject, с помощью кнопки преобразовывать в верхней части, за которой следует Камераи некоторые другие компоненты. Необходимо будет сбросить преобразование основной камеры, чтобы она правильно расположиться.

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

    reset transform

  4. Затем обновите компонент преобразования , чтобы он выглядел следующим образом:

    TRANSFORM-ПОЗИЦИОНИРОВАНИЕ
    X да Z
    0 1 0
    ПОВОРОТ ПРЕОБРАЗОВАНИЯ
    X да Z
    0 0 0
    ПРЕОБРАЗОВАНИЕ — МАСШТАБИРОВАНИЕ
    X да Z
    1 1 1

    set camera transform

Глава 5. Настройка сцены Unity

  1. Щелкните правой кнопкой мыши пустую область панели Иерархияв разделе трехмерный объект, добавьте плоскость.

    create new plane

  2. Выбрав объект плоскости , измените следующие параметры на панели инспектора:

    TRANSFORM-ПОЗИЦИОНИРОВАНИЕ
    X да Z
    0 0 4
    ПРЕОБРАЗОВАНИЕ — МАСШТАБИРОВАНИЕ
    X да Z
    10 1 10

    set plane position and scale

    scene view of plane

  3. Щелкните правой кнопкой мыши пустую область панели Иерархияв разделе трехмерный объекти добавьте куб.

    1. Переименование Куба в газебуттон (с выбранным кубом нажмите клавишу "F2").

    2. Измените следующие параметры на панели инспектора:

      TRANSFORM-ПОЗИЦИОНИРОВАНИЕ
      X да Z
      0 3 5

      set gaze button transform

      gaze button scene view

    3. Щелкните раскрывающийся список тег и выберите пункт Добавить тег , чтобы открыть панель « слои тегов».

      add new tag

      select plus

    4. Нажмите кнопку + (плюс) и в поле новое имя тега введите газебуттони нажмите кнопку сохранить.

      name new tag

    5. Щелкните объект газебуттон на панели Иерархия, а затем на панели инспектораназначьте созданный тег газебуттон .

      assign gaze button the new tag

  4. Щелкните правой кнопкой мыши объект газебуттон на панели Иерархияи добавьте пустой GameObject (который будет добавлен в качестве дочернего объекта).

  5. Выберите новый объект и переименуйте его в шапеспавнпоинт.

    1. Измените следующие параметры на панели инспектора:

      TRANSFORM-ПОЗИЦИОНИРОВАНИЕ
      X да Z
      0 -1 0

      update shape spawn point transform

      shape spawn point scene view

  6. Далее предстоит создать трехмерный текстовый объект, чтобы оставить отзыв о состоянии службы Azure.

    Щелкните правой кнопкой мыши газебуттон на панели Иерархия и добавьте трехмерный трехмерный объект 3D Object в качестве дочернего.

    create new 3D text object

  7. Переименуйте трехмерный текстовый объект в азурестатустекст.

  8. Измените преобразование объекта азурестатустекст следующим образом:

    TRANSFORM-ПОЗИЦИОНИРОВАНИЕ
    X да Z
    0 0 –0,6
    ПРЕОБРАЗОВАНИЕ — МАСШТАБИРОВАНИЕ
    X да Z
    0.1 0.1 0.1

    Примечание

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

  9. Измените компонент " Сетка текста " в соответствии с приведенным ниже:

    set text mesh component

    Совет

    Выбранный цвет имеет шестнадцатеричный цвет: 000000FF, хотя вы можете выбрать собственный, просто убедитесь, что он доступен для чтения.

  10. Теперь структура панели иерархии должна выглядеть следующим образом:

    Text mesh in hierarchy

  11. Теперь сцена должна выглядеть следующим образом:

    Text mesh in scene view

глава 6. импорт служба хранилища Azure для Unity

вы будете использовать служба хранилища Azure для Unity (который сам использует пакет SDK для .net для Azure). дополнительные сведения см. в статье служба хранилища Azure для Unity.

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

Чтобы импортировать пакет SDK в собственный проект, убедитесь, что вы скачали последнюю версию ". пакет unitypackage" из GitHub. Затем сделайте следующее.

  1. Добавьте файл . пакет unitypackage в Unity с помощью команды менюнастраиваемый пакет импорт активов.

  2. в появившемся окне импорт пакета Unity можно выбрать все в разделе подключаемый модульслужба хранилища. Снимите флажок все остальное, так как он не требуется для этого курса.

    import to package

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

  4. перейдите в папку служба хранилища в разделе подключаемые модули, в представлении Project и выберите толькоследующие подключаемые модули:

    • Microsoft.Data.Edm

    • Microsoft.Data.OData

    • Microsoft.WindowsAzure.Storage

    • Newtonsoft.Json.

    • System.Spatial

      uncheck Any platform

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

    apply platform dlls

    Примечание

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

  6. в папке служба хранилища подключаемый модуль выберите только:

    • Microsoft.Data.Services.Client

      set dont process for dlls

  7. установите флажок не обрабатывать в разделе Параметры платформы и нажмите кнопку применить.

    apply no processing

    Примечание

    Мы пометили этот подключаемый модуль как "не обрабатывать", так как при обработке этого подключаемого модуля в установщике сборок Unity возникли трудности. Подключаемый модуль по-прежнему будет работать, даже если он не обрабатывается.

Глава 7. Создание класса Азуресервицес

Первый класс, который предстоит создать, является классом азуресервицес .

Класс азуресервицес будет отвечать за:

  • Хранение учетных данных учетной записи Azure.

  • Вызов функции приложения Azure.

  • отправка и скачивание файла данных в облачной служба хранилища Azure.

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

  1. щелкните правой кнопкой мыши папку Asset , расположенную на панели Project создатьпапку. Назовите папку Scripts.

    create new folder

    call folder - scripts

  2. Дважды щелкните только что созданную папку, чтобы открыть ее.

  3. Щелкните правой кнопкой мыши внутри папки и выберите создатьскрипт C#. Вызовите скрипт азуресервицес.

  4. Дважды щелкните новый класс азуресервицес , чтобы открыть его с помощью Visual Studio.

  5. Добавьте следующие пространства имен в верхнюю часть азуресервицес:

        using System;
        using System.Threading.Tasks;
        using UnityEngine;
        using Microsoft.WindowsAzure.Storage;
        using Microsoft.WindowsAzure.Storage.File;
        using System.IO;
        using System.Net;
    
  6. Добавьте следующие поля инспектора в класс азуресервицес :

        /// <summary>
        /// Provides Singleton-like behavior to this class.
        /// </summary>
        public static AzureServices instance;
    
        /// <summary>
        /// Reference Target for AzureStatusText Text Mesh object
        /// </summary>
        public TextMesh azureStatusText;
    
  7. Затем добавьте следующие переменные члена в класс азуресервицес :

        /// <summary>
        /// Holds the Azure Function endpoint - Insert your Azure Function
        /// Connection String here.
        /// </summary>
    
        private readonly string azureFunctionEndpoint = "--Insert here you AzureFunction Endpoint--";
    
        /// <summary>
        /// Holds the Storage Connection String - Insert your Azure Storage
        /// Connection String here.
        /// </summary>
        private readonly string storageConnectionString = "--Insert here you AzureStorage Connection String--";
    
        /// <summary>
        /// Name of the Cloud Share - Hosts directories.
        /// </summary>
        private const string fileShare = "fileshare";
    
        /// <summary>
        /// Name of a Directory within the Share
        /// </summary>
        private const string storageDirectory = "storagedirectory";
    
        /// <summary>
        /// The Cloud File
        /// </summary>
        private CloudFile shapeIndexCloudFile;
    
        /// <summary>
        /// The Linked Storage Account
        /// </summary>
        private CloudStorageAccount storageAccount;
    
        /// <summary>
        /// The Cloud Client
        /// </summary>
        private CloudFileClient fileClient;
    
        /// <summary>
        /// The Cloud Share - Hosts Directories
        /// </summary>
        private CloudFileShare share;
    
        /// <summary>
        /// The Directory in the share that will host the Cloud file
        /// </summary>
        private CloudFileDirectory dir;
    

    Важно!

    Убедитесь, что значения конечных точек и строк подключения заменены значениями из хранилища Azure, расположенными на портале Azure.

  8. Теперь необходимо добавить код для методов "спящий" () и "начало" () . Эти методы будут вызываться при инициализации класса:

        private void Awake()
        {
            instance = this;
        }
    
        // Use this for initialization
        private void Start()
        {
            // Set the Status text to loading, whilst attempting connection to Azure.
            azureStatusText.text = "Loading...";
        }
    
        /// <summary>
        /// Call to the Azure Function App to request a Shape.
        /// </summary>
        public async void CallAzureFunctionForNextShape()
        {
    
        }
    

    Важно!

    В следующей главемы будем заполнять код для каллазурефунктионфорнекстшапе () .

  9. Удалите метод Update () , так как этот класс не будет его использовать.

  10. сохраните изменения в Visual Studio, а затем вернитесь в Unity.

  11. Щелкните и перетащите класс азуресервицес из папки Scripts в основной объект Camera на панели Иерархия.

  12. Выберите основную камеру, затем возьмите дочерний объект азурестатустекст из объекта газебуттон и поместите его в поле Целевой объект ссылки азурестатустекст в инспекторе, чтобы предоставить ссылку на скрипт азуресервицес .

    assign azure status text reference target

Глава 8. Создание класса Шапефактори

Следующий создаваемый скрипт является классом шапефактори . Роль этого класса заключается в том, чтобы создать новую фигуру при запросе и удержать историю созданных фигур в списке журнала фигур. каждый раз при создании фигуры список журнала фигур обновляется в классе AzureService , а затем сохраняется в служба хранилища Azure. при запуске приложения, если сохраненный файл найден в служба хранилища Azure, список журнала фигур извлекается и воспроизводится с помощью объекта 3d Text , который указывает, является ли созданная фигура из хранилища или новой.

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

  1. Перейдите к созданной ранее папке Scripts .

  2. Щелкните правой кнопкой мыши внутри папки и выберите создатьскрипт C#. Вызовите скрипт шапефактори.

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

  4. Убедитесь, что класс шапефактори содержит следующие пространства имен:

        using System.Collections.Generic;
        using UnityEngine;
    
  5. Добавьте указанные ниже переменные в класс шапефактори и замените функции Start () и спящие () на указанные ниже.

        /// <summary>
        /// Provide this class Singleton-like behaviour
        /// </summary>
        [HideInInspector]
        public static ShapeFactory instance;
    
        /// <summary>
        /// Provides an Inspector exposed reference to ShapeSpawnPoint
        /// </summary>
        [SerializeField]
        public Transform spawnPoint;
    
        /// <summary>
        /// Shape History Index
        /// </summary>
        [HideInInspector]
        public List<int> shapeHistoryList;
    
        /// <summary>
        /// Shapes Enum for selecting required shape
        /// </summary>
        private enum Shapes { Cube, Sphere, Cylinder }
    
        private void Awake()
        {
            instance = this;
        }
    
        private void Start()
        {
            shapeHistoryList = new List<int>();
        }
    
  6. Метод креатешапе () создает примитивные фигуры на основе указанного целочисленного параметра. Логический параметр используется для указания, является ли создаваемая в данный момент фигура из хранилища или новой. Поместите следующий код в класс шапефактори под предыдущими методами:

        /// <summary>
        /// Use the Shape Enum to spawn a new Primitive object in the scene
        /// </summary>
        /// <param name="shape">Enumerator Number for Shape</param>
        /// <param name="storageShape">Provides whether this is new or old</param>
        internal void CreateShape(int shape, bool storageSpace)
        {
            Shapes primitive = (Shapes)shape;
            GameObject newObject = null;
            string shapeText = storageSpace == true ? "Storage: " : "New: ";
    
            AzureServices.instance.azureStatusText.text = string.Format("{0}{1}", shapeText, primitive.ToString());
    
            switch (primitive)
            {
                case Shapes.Cube:
                newObject = GameObject.CreatePrimitive(PrimitiveType.Cube);
                break;
    
                case Shapes.Sphere:
                newObject = GameObject.CreatePrimitive(PrimitiveType.Sphere);
                break;
    
                case Shapes.Cylinder:
                newObject = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
                break;
            }
    
            if (newObject != null)
            {
                newObject.transform.position = spawnPoint.position;
    
                newObject.transform.localScale = new Vector3(0.5f, 0.5f, 0.5f);
    
                newObject.AddComponent<Rigidbody>().useGravity = true;
    
                newObject.GetComponent<Renderer>().material.color = UnityEngine.Random.ColorHSV(0f, 1f, 1f, 1f, 0.5f, 1f);
            }
        }
    
  7. не забудьте сохранить изменения в Visual Studio перед возвратом в Unity.

  8. В редакторе Unity щелкните и перетащите класс шапефактори из папки сценарии в объект Main на панели Иерархия.

  9. Выбрав основную камеру, вы увидите, что в компоненте скрипта шапефактори отсутствует ссылка на точку порождения . Чтобы устранить эту проблему, перетащите объект шапеспавнпоинт с панели Иерархия в целевой объект ссылки на точку порождения .

    set shape factory reference target

Глава 9. Создание класса «взгляд»

Последний скрипт, который необходимо создать, является классом « взгляд ».

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

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

  1. Перейдите к созданной ранее папке Scripts .

  2. щелкните правой кнопкой мыши на панели Project и создайтескрипт C#. Вызовите скрипт взгляд.

  3. Дважды щелкните новый скрипт " Взгляните ", чтобы открыть его с помощью Visual Studio.

  4. Убедитесь, что в начале скрипта включено следующее пространство имен:

        using UnityEngine;
    
  5. Затем добавьте следующие переменные в класс Взгляните :

        /// <summary>
        /// Provides Singleton-like behavior to this class.
        /// </summary>
        public static Gaze instance;
    
        /// <summary>
        /// The Tag which the Gaze will use to interact with objects. Can also be set in editor.
        /// </summary>
        public string InteractibleTag = "GazeButton";
    
        /// <summary>
        /// The layer which will be detected by the Gaze ('~0' equals everything).
        /// </summary>
        public LayerMask LayerMask = ~0;
    
        /// <summary>
        /// The Max Distance the gaze should travel, if it has not hit anything.
        /// </summary>
        public float GazeMaxDistance = 300;
    
        /// <summary>
        /// The size of the cursor, which will be created.
        /// </summary>
        public Vector3 CursorSize = new Vector3(0.05f, 0.05f, 0.05f);
    
        /// <summary>
        /// The color of the cursor - can be set in editor.
        /// </summary>
        public Color CursorColour = Color.HSVToRGB(0.0223f, 0.7922f, 1.000f);
    
        /// <summary>
        /// Provides when the gaze is ready to start working (based upon whether
        /// Azure connects successfully).
        /// </summary>
        internal bool GazeEnabled = false;
    
        /// <summary>
        /// The currently focused object.
        /// </summary>
        internal GameObject FocusedObject { get; private set; }
    
        /// <summary>
        /// The object which was last focused on.
        /// </summary>
        internal GameObject _oldFocusedObject { get; private set; }
    
        /// <summary>
        /// The info taken from the last hit.
        /// </summary>
        internal RaycastHit HitInfo { get; private set; }
    
        /// <summary>
        /// The cursor object.
        /// </summary>
        internal GameObject Cursor { get; private set; }
    
        /// <summary>
        /// Provides whether the raycast has hit something.
        /// </summary>
        internal bool Hit { get; private set; }
    
        /// <summary>
        /// This will store the position which the ray last hit.
        /// </summary>
        internal Vector3 Position { get; private set; }
    
        /// <summary>
        /// This will store the normal, of the ray from its last hit.
        /// </summary>
        internal Vector3 Normal { get; private set; }
    
        /// <summary>
        /// The start point of the gaze ray cast.
        /// </summary>
        private Vector3 _gazeOrigin;
    
        /// <summary>
        /// The direction in which the gaze should be.
        /// </summary>
        private Vector3 _gazeDirection;
    

Важно!

Некоторые из этих переменных могут быть изменены в редакторе.

  1. Теперь необходимо добавить код для методов спящего режима () и Start () .

        /// <summary>
        /// The method used after initialization of the scene, though before Start().
        /// </summary>
        private void Awake()
        {
            // Set this class to behave similar to singleton
            instance = this;
        }
    
        /// <summary>
        /// Start method used upon initialization.
        /// </summary>
        private void Start()
        {
            FocusedObject = null;
            Cursor = CreateCursor();
        }
    
  2. Добавьте следующий код, который создаст объект курсора при запуске, а также метод Update () , который будет выполнять метод райкаст вместе с переключением логического газинаблед.

        /// <summary>
        /// Method to create a cursor object.
        /// </summary>
        /// <returns></returns>
        private GameObject CreateCursor()
        {
            GameObject newCursor = GameObject.CreatePrimitive(PrimitiveType.Sphere);
            newCursor.SetActive(false);
    
            // Remove the collider, so it doesn't block raycast.
            Destroy(newCursor.GetComponent<SphereCollider>());
            newCursor.transform.localScale = CursorSize;
    
            newCursor.GetComponent<MeshRenderer>().material = new Material(Shader.Find("Diffuse"))
            {
                color = CursorColour
            };
    
            newCursor.name = "Cursor";
    
            newCursor.SetActive(true);
    
            return newCursor;
        }
    
        /// <summary>
        /// Called every frame
        /// </summary>
        private void Update()
        {
            if(GazeEnabled == true)
            {
                _gazeOrigin = Camera.main.transform.position;
    
                _gazeDirection = Camera.main.transform.forward;
    
                UpdateRaycast();
            }
        }
    
  3. Затем добавьте метод упдатерайкаст () , который выполнит проецирование райкаст и определит цель попадания.

        private void UpdateRaycast()
        {
            // Set the old focused gameobject.
            _oldFocusedObject = FocusedObject;
    
            RaycastHit hitInfo;
    
            // Initialise Raycasting.
            Hit = Physics.Raycast(_gazeOrigin,
                _gazeDirection,
                out hitInfo,
                GazeMaxDistance, LayerMask);
    
            HitInfo = hitInfo;
    
            // Check whether raycast has hit.
            if (Hit == true)
            {
                Position = hitInfo.point;
    
                Normal = hitInfo.normal;
    
                // Check whether the hit has a collider.
                if (hitInfo.collider != null)
                {
                    // Set the focused object with what the user just looked at.
                    FocusedObject = hitInfo.collider.gameObject;
                }
                else
                {
                    // Object looked on is not valid, set focused gameobject to null.
                    FocusedObject = null;
                }
            }
            else
            {
                // No object looked upon, set focused gameobject to null.
                FocusedObject = null;
    
                // Provide default position for cursor.
                Position = _gazeOrigin + (_gazeDirection * GazeMaxDistance);
    
                // Provide a default normal.
                Normal = _gazeDirection;
            }
    
            // Lerp the cursor to the given position, which helps to stabilize the gaze.
            Cursor.transform.position = Vector3.Lerp(Cursor.transform.position, Position, 0.6f);
    
            // Check whether the previous focused object is this same 
            //    object. If so, reset the focused object.
            if (FocusedObject != _oldFocusedObject)
            {
                ResetFocusedObject();
    
                if (FocusedObject != null)
                {
                if (FocusedObject.CompareTag(InteractibleTag.ToString()))
                {
                        // Set the Focused object to green - success!
                        FocusedObject.GetComponent<Renderer>().material.color = Color.green;
    
                        // Start the Azure Function, to provide the next shape!
                        AzureServices.instance.CallAzureFunctionForNextShape();
                    }
                }
            }
        }
    
  4. Наконец, добавьте метод ресетфокуседобжект () , который будет переключать текущий цвет объектов газебуттон, указывая, создает ли он новую фигуру.

        /// <summary>
        /// Reset the old focused object, stop the gaze timer, and send data if it
        /// is greater than one.
        /// </summary>
        private void ResetFocusedObject()
        {
            // Ensure the old focused object is not null.
            if (_oldFocusedObject != null)
            {
                if (_oldFocusedObject.CompareTag(InteractibleTag.ToString()))
                {
                    // Set the old focused object to red - its original state.
                    _oldFocusedObject.GetComponent<Renderer>().material.color = Color.red;
                }
            }
        }
    
  5. сохраните изменения в Visual Studio перед возвратом в Unity.

  6. Щелкните и Перетащите класс «указатель» из папки «скрипты» в основной объект Camera на панели «Иерархия».

Глава 10. Завершение работы с классом Азуресервицес

После выполнения других сценариев теперь можно завершить класс азуресервицес . Это достигается с помощью следующих средств:

  1. Добавление нового метода с именем креатеклаудидентитясинк ()для настройки переменных проверки подлинности, необходимых для взаимодействия с Azure.

    Этот метод также проверяет наличие ранее сохраненного файла, содержащего список фигур.

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

    Если файл не найден, будет включен взгляд, позволяющий пользователю создавать фигуры при просмотре объекта газебуттон в сцене.

        /// <summary>
        /// Create the references necessary to log into Azure
        /// </summary>
        private async void CreateCloudIdentityAsync()
        {
            // Retrieve storage account information from connection string
            storageAccount = CloudStorageAccount.Parse(storageConnectionString);
    
            // Create a file client for interacting with the file service.
            fileClient = storageAccount.CreateCloudFileClient();
    
            // Create a share for organizing files and directories within the storage account.
            share = fileClient.GetShareReference(fileShare);
    
            await share.CreateIfNotExistsAsync();
    
            // Get a reference to the root directory of the share.
            CloudFileDirectory root = share.GetRootDirectoryReference();
    
            // Create a directory under the root directory
            dir = root.GetDirectoryReference(storageDirectory);
    
            await dir.CreateIfNotExistsAsync();
    
            //Check if the there is a stored text file containing the list
            shapeIndexCloudFile = dir.GetFileReference("TextShapeFile");
    
            if (!await shapeIndexCloudFile.ExistsAsync())
            {
                // File not found, enable gaze for shapes creation
                Gaze.instance.GazeEnabled = true;
    
                azureStatusText.text = "No Shape\nFile!";
            }
            else
            {
                // The file has been found, disable gaze and get the list from the file
                Gaze.instance.GazeEnabled = false;
    
                azureStatusText.text = "Shape File\nFound!";
    
                await ReplicateListFromAzureAsync();
            }
        }
    
  2. Следующий фрагмент кода находится в методе Start () ; где выполняется вызов метода креатеклаудидентитясинк () . Вы можете скопировать свой текущий метод Start () следующим образом:

        private void Start()
        {
            // Disable TLS cert checks only while in Unity Editor (until Unity adds support for TLS)
    #if UNITY_EDITOR
            ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
    #endif
    
            // Set the Status text to loading, whilst attempting connection to Azure.
            azureStatusText.text = "Loading...";
    
            //Creating the references necessary to log into Azure and check if the Storage Directory is empty
            CreateCloudIdentityAsync();
        }
    
  3. Заполните код метода каллазурефунктионфорнекстшапе (). Вы будете использовать ранее созданную приложение-функция Azure для запроса индекса фигуры. После получения новой фигуры этот метод отправит форму в класс шапефактори , чтобы создать новую фигуру в сцене. Используйте приведенный ниже код, чтобы завершить тело каллазурефунктионфорнекстшапе ().

        /// <summary>
        /// Call to the Azure Function App to request a Shape.
        /// </summary>
        public async void CallAzureFunctionForNextShape()
        {
            int azureRandomInt = 0;
    
            // Call Azure function
            HttpWebRequest webRequest = WebRequest.CreateHttp(azureFunctionEndpoint);
    
            WebResponse response = await webRequest.GetResponseAsync();
    
            // Read response as string
            using (Stream stream = response.GetResponseStream())
            {
                StreamReader reader = new StreamReader(stream);
    
                String responseString = reader.ReadToEnd();
    
                //parse result as integer
                Int32.TryParse(responseString, out azureRandomInt);
            }
    
            //add random int from Azure to the ShapeIndexList
            ShapeFactory.instance.shapeHistoryList.Add(azureRandomInt);
    
            ShapeFactory.instance.CreateShape(azureRandomInt, false);
    
            //Save to Azure storage
            await UploadListToAzureAsync();
        }
    
  4. добавьте метод для создания строки путем сцепления целых чисел, хранящихся в списке журнала фигур, и сохранения их в файле служба хранилища Azure.

        /// <summary>
        /// Upload the locally stored List to Azure
        /// </summary>
        private async Task UploadListToAzureAsync()
        {
            // Uploading a local file to the directory created above
            string listToString = string.Join(",", ShapeFactory.instance.shapeHistoryList.ToArray());
    
            await shapeIndexCloudFile.UploadTextAsync(listToString);
        }
    
  5. добавьте метод для получения текста, хранящегося в файле, расположенном в файле служба хранилища Azure , и десериализация его в список.

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

        ///<summary>
        /// Get the List stored in Azure and use the data retrieved to replicate 
        /// a Shape creation pattern
        ///</summary>
        private async Task ReplicateListFromAzureAsync()
        {
            string azureTextFileContent = await shapeIndexCloudFile.DownloadTextAsync();
    
            string[] shapes = azureTextFileContent.Split(new char[] { ',' });
    
            foreach (string shape in shapes)
            {
                int i;
    
                Int32.TryParse(shape.ToString(), out i);
    
                ShapeFactory.instance.shapeHistoryList.Add(i);
    
                ShapeFactory.instance.CreateShape(i, true);
    
                await Task.Delay(500);
            }
    
            Gaze.instance.GazeEnabled = true;
    
            azureStatusText.text = "Load Complete!";
        }
    
  7. сохраните изменения в Visual Studio перед возвратом в Unity.

Глава 11. Создание решения UWP

Чтобы начать процесс сборки:

  1. последовательно выберите файлсборка Параметры.

    build the app

  2. Щелкните Построить. Unity запустит окно проводника , в котором необходимо создать, а затем выбрать папку для сборки приложения. Создайте эту папку сейчас и назовите ее appName. Затем выберите папку приложения и нажмите кнопку выбрать папку.

  3. Unity начнет сборку проекта в папку приложения .

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

Глава 12. Развертывание приложения

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

  1. Перейдите к папке приложения , созданной в последней главе. Вы увидите файл с именем приложения с расширением SLN, который следует дважды щелкнуть, чтобы открыть его в Visual Studio.

  2. На платформе решениявыберите x86, локальный компьютер.

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

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

    • определите IP-адрес HoloLens, который можно найти в Параметрысети интернетWi-FiAdvanced (дополнительные параметры). IPv4 — это адрес, который следует использовать.
    • Убедитесь, что включенрежим разработчика ; найдено в Параметрыобновлений безопасностидля разработчиков.

    deploy solution

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

  5. Теперь приложение должно отобразиться в списке установленных приложений, готовых к запуску и тестированию.

готовые функции Azure и приложение служба хранилища

поздравляем, вы создали приложение смешанной реальности, которое использует как функции Azure, так и службы служба хранилища Azure. Приложение сможет рисовать на сохраненных данных и предоставить действие на основе этих данных.

final product -end

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

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

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

Упражнение 2

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