Поделиться через


HoloLens (1-го поколения) и Azure 305: функции и хранилище


Примечание.

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


окончательный продукт -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 с проектом Unity. Это ваша задача использовать знания, полученные от этого курса, чтобы улучшить приложение смешанной реальности.

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

Курс HoloLens Иммерсивные гарнитуры
MR и Azure 305: функции и хранилище ✔️ ✔️

Примечание.

Хотя этот курс в основном ориентирован на гарнитуры Windows Смешанная реальность иммерсивные (VR), вы также можете применить то, что вы узнаете в этом курсе к Microsoft HoloLens. При выполнении курса вы увидите заметки о любых изменениях, которые могут потребоваться для поддержки HoloLens.

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

Примечание.

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

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

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

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

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

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

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

    Примечание.

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

  2. После входа нажмите кнопку "Создать" в левом верхнем углу и найдите учетную запись хранения и нажмите клавишу ВВОД.

    Поиск службы хранилища Azure

    Примечание.

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

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

    создание службы

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

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

    2. Для модели развертывания выберите Resource Manager.

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

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

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

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

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

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

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

      Если вы хотите узнать больше о группах ресурсов Azure, посетите статью группы ресурсов.

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

    11. Нажмите кнопку создания.

      входные сведения о службе

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

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

    новое уведомление на портале Azure

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

    Перейти к ресурсу

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

    ключи доступа

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

    копирование строка подключения

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

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

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

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

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

    Создание приложения-функции

    Примечание.

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

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

    Сведения о приложении-функции

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

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

    2. Выберите предпочтительную подписку.

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

      Если вы хотите узнать больше о группах ресурсов Azure, посетите статью группы ресурсов.

    4. Для этого упражнения выберите Windows в качестве выбранной ОС.

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

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

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

    8. Оставьте Application Insights отключенным для этого упражнения.

      Сведения о входных приложениях-функциях

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

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

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

    новое уведомление на портале Azure

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

    Перейдите в приложение-функцию ресурсов

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

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

    создание новой функции

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

    Выбор веб-перехватчика csharp

  11. Вы должны перейти на кодовую страницу (run.csx), если нет, щелкните только что созданную функцию в списке "Функции" на панели слева.

    открытие новой функции

  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 и запишите отображаемую конечную точку. Вам потребуется вставить его в класс AzureServices , который вы создадите позже в этом курсе.

    Получение конечной точки функции

    Вставка конечной точки функции

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

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

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

Примечание.

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

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

    Создание проекта unity

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

    Присвойте новому проекту unity имя

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

    Установка Visual Studio в качестве редактора скриптов

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

    переключение платформы на uwp

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

    1. Целевое устройство имеет значение Any Device.

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

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

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

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

    5. Для сборки и запуска задано значение Local Machine

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

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

        добавление открытых сцен

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

        Создание папки сцен

      3. Откройте только что созданную папку "Сцены", а затем в текстовом поле : текстовое поле, введите FunctionsScene, а затем нажмите клавишу SAVE.

        Сохранение сцены функций

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

    Оставьте параметры сборки по умолчанию

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

    Параметры проигрывателя в инспекторе

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

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

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

      • InternetClient;

        Установка возможностей

    3. Далее вниз по панели в параметрах XR (приведенных ниже параметров публикации), установите флажок "Поддержка виртуальной реальности", убедитесь, что пакет SDK для Windows Смешанная реальность добавлен.

      Настройка параметров XR

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

    тик проектов c#

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

  11. Сохраните сцену и проект (ФАЙЛ>СОХРАНИТЬ СЦЕНУ или ФАЙЛ>СОХРАНИТЬ ПРОЕКТ).

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

Внимание

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

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

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

  3. Для этого выберите значок Шестеренки рядом с компонентом преобразования камеры и нажмите кнопку "Сброс".

    Преобразование сброса

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

Преобразование — положение

X Y Z
0 1 0

Преобразование — поворот

X Y Z
0 0 0

Преобразование — масштабирование

X Y Z
1 1 1

Настройка преобразования камеры

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

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

    создание новой плоскости

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

Преобразование — положение

X Y Z
0 0 4

Преобразование — масштабирование

X Y Z
10 1 10

Установка положения плоскости и масштабирования

представление сцены плоскости

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

    1. Переименуйте куб в GazeButton (с выбранным кубом нажмите клавишу F2).

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

      X Y Z
      0 3 5

      Настройка преобразования кнопки взгляда

      Представление сцены кнопки взгляда

    3. Нажмите кнопку раскрывающегося списка тегов и нажмите кнопку "Добавить тег", чтобы открыть область "Теги и слои".

      добавление нового тега

      выбор плюса

    4. Нажмите кнопку +(плюс) и в поле "Имя нового тега", введите GazeButton и нажмите клавишу SAVE.

      имя нового тега

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

      Назначьте кнопку взгляда новый тег

  2. Щелкните правой кнопкой мыши объект GazeButton на панели иерархии и добавьте пустой gameObject (который будет добавлен в качестве дочернего объекта).

  3. Выберите новый объект и переименуйте его ShapeSpawnPoint.

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

      X Y Z
      0 -1 0

      Обновление преобразования точки с помощью точки обновления фигуры

      Представление сцены с точки точки формирования фигуры

  4. Затем вы создадите трехмерный текстовый объект для предоставления отзывов о состоянии службы Azure.

    Щелкните правой кнопкой мыши элемент GazeButton на панели иерархии и добавьте трехмерный объект 3D>Text в качестве дочернего объекта.

    создание нового трехмерного текстового объекта

  5. Переименуйте трехмерный текстовый объект в AzureStatusText.

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

    X Y Z
    0 0 –0,6
  7. Измените масштаб преобразования объекта AzureStatusText следующим образом: | X | Y | Z | :---: | :---: | :---: | | 0.1 | 0.1 | 0.1 | 0.1 |

    Примечание.

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

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

    Установка компонента сетки текста

    Совет

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

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

    Текстовая сетка в иерархии

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

    Сетка текста в представлении сцены

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

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

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

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

  1. Добавьте файл unitypackage в Unity с помощью> параметра меню "Импорт>пользовательского пакета ресурсов".

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

    импорт в пакет

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

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

    • Microsoft.Data.Edm

    • Microsoft.Data.OData

    • Microsoft.WindowsAzure.Storage

    • Newtonsoft.Json

    • System.Spatial

      снимите флажок

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

    применение библиотек DLL платформы

    Примечание.

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

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

    • Microsoft.Data.Services.Client

      Набор не обрабатывается для библиотек DLL

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

    не применять обработку

    Примечание.

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

Глава 7. Создание класса AzureServices

Первый класс, который вы собираетесь создать, — это класс AzureServices .

Класс AzureServices будет отвечать за:

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

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

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

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

  1. Щелкните правой кнопкой мыши папку ресурса , расположенную на панели проекта, создайте>папку. Назовите скрипты папок.

    создание новой папки

    Папка вызова — скрипты

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

  3. Щелкните правой кнопкой мыши в папке скрипт >C#. Вызовите скрипт AzureServices.

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

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

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

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

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

    Внимание

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

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

        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()
        {
    
        }
    

    Внимание

    Мы заполним код для CallAzureFunctionForNextShape() в следующей главе.

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

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

  11. Щелкните и перетащите класс AzureServices из папки "Скрипты" в объект Main Camera на панели иерархии.

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

    Назначение целевого объекта ссылки на текст состояния Azure

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

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

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

  1. Перейдите в папку "Скрипты", созданную ранее.

  2. Щелкните правой кнопкой мыши в папке скрипт >C#. Вызовите скрипт ShapeFactory.

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

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

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

        /// <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. Метод CreateShape() создает примитивные фигуры на основе предоставленного целочисленного параметра. Логический параметр используется для указания того, является ли созданная в данный момент фигура из хранилища или новой. Поместите следующий код в класс ShapeFactory ниже предыдущих методов:

        /// <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, щелкните и перетащите класс ShapeFactory из папки "Скрипты " в объект Main Camera на панели иерархии.

  9. При выборе основной камеры вы заметите, что компонент скрипта ShapeFactory отсутствует ссылка spawn Point . Чтобы исправить его, перетащите объект ShapeSpawnPoint из панели иерархии в целевой объект ссылки Spawn Point .

    Установка эталонного целевого объекта фабрики фигур

Глава 9. Создание класса Gaze

Последний скрипт, который необходимо создать, — это класс Gaze .

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

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

  1. Перейдите в папку "Скрипты", созданную ранее.

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

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

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

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

        /// <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. Теперь необходимо добавить код для методов Awake() и 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(), который будет запускать метод Raycast, а также место, где логическое значение GazeEnabled переключается:

        /// <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. Затем добавьте метод UpdateRaycast(), который будет проектировать Raycast и обнаруживать целевой объект попадания.

        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. Наконец, добавьте метод ResetFocusedObject(), который переключит объекты GazeButton текущего цвета, указывая, создает ли она новую фигуру или нет.

        /// <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. Щелкните и перетащите класс Gaze из папки "Скрипты" в объект Main Camera на панели иерархии.

Глава 10. Завершение класса AzureServices

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

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

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

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

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

        /// <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(), где вызов будет выполнен в метод CreateCloudIdentityAsync(). Вы можете скопировать текущий метод 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. Заполните код метода CallAzureFunctionForNextShape(). Вы будете использовать ранее созданное приложение-функцию Azure для запроса индекса фигуры. После получения новой фигуры этот метод отправит фигуру в класс ShapeFactory , чтобы создать новую фигуру в сцене. Используйте приведенный ниже код, чтобы завершить текст CallAzureFunctionForNextShape().

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

    создание приложения

  2. Нажмите кнопку " Создать". Unity запустит окно проводник, в котором необходимо создать, а затем выбрать папку для сборки приложения. Создайте папку и присвойте ей имя приложения. Затем с выбранной папкой приложения нажмите клавишу SELECT FOLDER.

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

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

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

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

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

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

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

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

    • Ознакомься с IP-адресом HoloLens, который можно найти в> разделе "Параметры сети" и "Расширенные параметры Интернета>Wi-Fi>".IPv4 — это адрес, который следует использовать.
    • Убедитесь, что режим разработчика включен; в разделе "Параметры>обновления" и "Безопасность>для разработчиков".

    развертывание решения

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

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

Готовое приложение Функции Azure и хранилища

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

конечный продукт -end

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

Упражнение 1

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

Упражнение 2

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