Продукти та технології:
Unity, C #, віртуальна реальність
У статті розглядаються:
- створення базового UI в віртуальної реальності;
- підключення до зовнішніх даних в додатку віртуальної реальності;
- зв'язування з даними ігрових об'єктів в Unity.
Віртуальна реальність (VR) надає не тільки унікальні можливості розробникам, а й ставить перед ними важкі завдання. З одного боку, є можливість забезпечити занурення в VR, не пов'язану існуючої парадигмою двомірних UI. З іншого боку, виникає проблема створення вражаючої VR, яка є чимось більшим простого тривимірного представлення двомірного екрану. На щастя, деякі фундаментальні основи розробки додатків і дизайну UI схожі, наприклад створення вистави «основні / докладні дані» (master / details), отримання введення від користувача і взаємодія між додатками через сервіси. У цій статті я досліджую ці області в контексті створення бізнес-додатки віртуальної реальності, щоб ви зрозуміли, як приступити до розробки власних VR-додатків.
Чому VR?
Зараз саме час зайнятися розробкою VR-додатків через появу відмінного інструментарію начебто Unity і порівняно невеликого ринку VR.
Створення додатків для таких VR-пристроїв, як Samsung Gear VR і Google Cardboard, - хороша відправна точка для розробників, початківців готувати свій контент для каналів збуту бюджетної продукції. При розробці в розрахунку на Mixed Reality VR-додатки можна перенести на HoloLens, оскільки інструментарій однаковий і контент теж може бути однаковий. Єдина відмінність - код, який виконує завдання (наприклад, Gaze або Raycast, які ми розглянемо далі в цій статті), і використання деяких унікальних функцій HoloLens, таких як мова, просторове картування (spatial mapping) і жести. Трохи досліджень і експериментів, і ви зможете перетворити своє VR-додаток в додаток HoloLens.
Я не буду вдаватися в надмірні подробиці підготовки проекту VR. Замість цього я раджу вивчити проект Unity VR Samples в Unity Asset Store (bit.ly/1qYLBX9). Проект в цій статті я створю з нуля, але буду використовувати скрипти з проекту Unity VR Samples, щоб задіяти існуючий код для стандартних завдань (наприклад, щоб зробити об'єкт інтерактивним). Я рекомендую створити порожній проект Unity і імпортувати Unity VR Samples для посилання поза створюваного в цій статті проекту. Unity VR Samples має масу чудового контенту, але побудований як автономне додаток і вимагає деякого додаткового конфігурування для виконання сцени поза включених сцен. Тримайте Unity VR Samples відкритим і доступним, так як в ньому є кілька сценаріїв, які знадобляться в моєму проекті. Для цієї статті я буду використовувати Unity 5.3 з підтримкою інструментарію Android, щоб мати можливість створити додаток для пристрою Samsung Gear VR.
Система Contoso Travel
приступаємо
Потім поновіть Player Settings для мобільного VR. Для цього відкрийте Edit | Project Settings | Player і виберіть розділ Other Settings. У цьому розділі є параметр Virtual Reality Supported. Встановіть прапорець поруч з ним, щоб світ розпізнав як VR-додаток. Завдяки цьому об'єкт Main Camera, вже існуючий в Unity буде автоматично перетворено в камеру VR.
Для відряджених VR може дати попереднє уявлення про офіс, в який вони направляються, або про місця, які потрібно подивитися.
Тепер, налаштувавши додаток, підготуйте сцену. У вікні Hierarchy додайте куб з масштабом x = 10, y = 0.1 і z = 10. Скиньте позицію куба, щоб центрувати його за координатами x = 0, y = 0 і z = 0 як сплощений куб в світі. За рахунок цього у вас з'явиться нижня стінка для світу, що дасть користувачам відчуття простору і основи (grounding), а також місце для сутностей в цьому світі, де вони будуть розташовуватися. Як і в двомірних додатках, ви повинні подбати про те, щоб користувач розумів, де буде з'являтися контент і відбуватися взаємодія з ним. Це допомагає користувачам орієнтуватися в додатку. У разі ContosoTravel всі дії будуть відбуватися в межах цього об'єкта стінок світу.
У цьому світі вам буде потрібно об'єкт, який буде виконувати маршалинга даних через додаток. Створіть Empty Game Object в вікні Hierarchy і перейменуйте цей об'єкт в TravelerManager. Він буде джерелом всіх даних про відряджених в додатку. Виділивши ігровий об'єкт TravelerManager, клацніть Add Component | New Script. Назвіть скрипт TravelerManager і клацніть Create and Add. Це призведе до створення нового скрипта для обробки логіки TravelerManager.
Додаток для управління відрядженнями має бачити всіх відряджених від даної організації. Для цього додайте новий ігровий об'єкт (Game Object) до ієрархії (Hierarchy) і назвіть його TravelerTemplate. Це буде об'єкт, який з'явиться в кожного відрядженого, представленого в системі. Якщо ви знайомі з заготовками (prefabs), використовуйте персонаж, сконструйований вами, або візьміть щось з Asset Store. Для свого застосування я буду використовувати нізкополігональних персонажі, знайдені в Asset Store, що надають світу кумедний вигляд. Для TravelerTemplate підійде будь-який ігровий об'єкт - заготівля, куб, сфера та ін. Додавши TravelerTemplate, вимкніть цей ігровий об'єкт, клацнувши прапорець поруч з ім'ям ігрового об'єкта у вікні Inspector. Після цього TravelerTemplate зникне з екрану.
Нарешті, додайте в свій проект наступні скрипти з проекту Unity VR Samples: VREyeRaycast, VRInput, VRInteractiveItem і Reticle. Конкретне призначення цих скриптів ми обговоримо, коли я буду використовувати їх далі в цій статті, але вони позбавили мене від чималої частини роботи.
Підготовка класу TravelerManager
У Unity двічі клацніть скрипт TravelerManager, щоб відкрити його в MonoDevelop або Visual Studio. Додайте в компонент код з рис. 1.
Мал. 1. Скриптова компонент TravelerManager
У GetTravelers об'єкт WWW з Unity застосовується для підключення до наданого URL. При використанні ключового слова yield об'єкт WWW повертається, поки не завершиться перевіркою якості isDone. Після закінчення завантаження по URL властивість isDone дорівнюватиме true, після чого текст, повернутий API-викликом, передається методу DisplayTravelers. Об'єкт WWW можна використовувати для асинхронної відправки та отримання даних, щоб в майбутньому у додатки була функціональність для додавання об'єктів відряджених співробітників. Повну документацію на об'єкт WWW см. На сайті Unity за посиланням bit.ly/2alFoML.
Потім ви приймаєте результат від API і перетворите його в щось, що користувач зможе побачити в додатку. Перш ніж показувати відряджених в різних місцях на карті, ви повинні створити ці місця в світі. Поверніться в дизайнер Unity і створіть порожній ігровий об'єкт в корені дерева Hierarchy. Назвіть цей порожній ігровий об'єкт Location Container. Встановіть позицію Location Container як X = 0, Y = 0, Z = 0 (в центрі світу). При виділеному Location Container створіть кілька порожніх дочірніх ігрових об'єктів, розкиданих по нижньому боці раніше створеного куба. Ці порожні ігрові об'єкти представляють аеропорти, а нижня сторона куба подібна карті. У методі DisplayTravelers ви шукаєте місто призначення для відрядженого і співвідносите його з одним з цих порожніх ігрових об'єктів. Перейменуйте порожні ігрові об'єкти в назви яких-небудь аеропортів. Я використовував BWI, MSP і SFO. Щоб закінчити з аеропортами, створіть тег для Game Objects з ім'ям Airport - тоді ви зможете знаходити всі аеропорти за значенням одного тега. Щоб створити позначку перейдіть в ліву верхню частину вікна Inspector для об'єкта, клацніть список, що розкривається і виберіть New Tag. Ви можете створити новий тег і в варіанті, коли виділені всі порожні ігрові об'єкти, що дозволить разом задати для всіх цих об'єктів один тег.
Після методу getTravelers додайте код, показаний на рис. 2.
Мал. 2. Перетворення JSON-об'єктів Traveler в ігрові об'єкти Unity
Використовуючи безкоштовний скрипт JSONObject з Unity Asset Store (bit.ly/2akN9p9), ви можете перетворити JSON-текст в об'єкт C #-коду Traveler. Потім за допомогою методу Instantiate ви створюєте копію TravelerTemplate, привласнюєте їй координати за умовчанням і задаєте ігровому об'єкту ім'я відрядженого. Це ім'я знадобиться в додатку надалі, оскільки воно буде використовуватися для ідентифікації відрядженого в списку. Далі ви знаходите все ігрові об'єкти, помічені тегом Airport. Це дає вам набір об'єктів Airport, які ви можете перебирати в циклі і знаходити потрібний об'єкт по імені, щоб помістити відрядженого до відповідного аеропорт. Використовуючи раніше підготовлені теги, ви легко знаходите потрібні ігрові об'єкти Airport. В кінці методу додайте об'єкт traveler в TravelerList, щоб ви могли потім посилатися на дані про це направленому. Отже, у вас є основний список відряджених, що відображаються у вашому світі. Тепер саме час вирішити користувачам вибирати відрядженого, щоб ви могли показувати детальну інформацію про це працівника.
Вибір об'єкта відрядженого співробітника
У VR вибір відрядженого співробітника здійснюється поглядом на об'єкт. Щоб дізнатися, чи дивиться користувач на будь-якого відрядженого співробітника, ви повинні використовувати об'єкт Raycast. Raycast - це невидимий промінь, що виходить з камери і дозволяє системі виявляти, коли об'єкт з компонентом-колайдером (collider component) в ньому перетинається з променем. Використовуючи Raycast, ваш код може розпізнавати, коли користувач дивиться на який-небудь об'єкт, який повинен на це відреагувати. Раніше ви імпортували скрипт VREyeRaycast, який реалізує всю логіку, яка необхідні для створення Raycast в камері. Додайте скрипт VREyeRaycast в Main Camera. Вам також знадобиться додати скрипт Reticle в цю камеру, щоб надати UI-компонент, який показує, куди дивиться користувач.
Використовуючи Raycast, ваш код може розпізнавати, коли користувач дивиться на який-небудь об'єкт, який повинен на це відреагувати.
Помістивши Raycast в камеру, потрібно оновити TravelerTemplate, щоб знати, як реагувати на перетин з Raycast. Для цього додайте скрипт VRInteractiveItem в TravelerTemplate. Цей скрипт забезпечує швидке налаштування для роботи з подій, що генеруються, коли Raycast перетинається з об'єктом, залишає об'єкт або навіть захоплює подія клацання.
Далі ви створюєте скрипт з ім'ям TravelerInteraction, який реалізує події в скрипті VRInteractiveItem. Для цієї програми ви будете використовувати події OnOver, OnOut і OnClick. Коли користувач дивиться на об'єкт Traveler, той буде міняти свій зовнішній вигляд, а коли користувач відводить від нього погляд, зовнішній вигляд цього об'єкта буде відновлюватися. Якщо користувач дивиться на об'єкт Traveler і робить клацання, з'являється діалог, що показує ім'я відрядженого співробітника, посаду і місце призначення. Ось скрипт TravelerInteraction:
У цьому блоці коду ви спочатку визначаєте, чи показується діалог. Якщо так, ви відключаєте діалог, щоб приховати його. Ні - отримуєте об'єкт тексту і привласнюєте його значення імені і місця призначення Traveler. Коли ви спочатку створювали об'єкт Traveler, ви вказали ім'я відрядженого співробітника в якості імені ігрового об'єкта, що представляє цього співробітника. За допомогою LINQ ви можете вести пошук в списку відряджених з цього імені, щоб отримати детальну інформацію про даний співробітника. Простоти заради було задіяно ім'я відрядженого, але в більших і складних системах набагато краще застосовувати унікальний ідентифікатор кожного відрядженого. З приводу LINQ пам'ятайте, що продуктивність - це головне в мобільному VR-додатку. LINQ здатна робити дуже багато, але ціною чималих витрат, так що будьте уважні при використанні LINQ і застосовуйте її тільки там, де без неї не обійтися, а не просто для зручності. Тут LINQ використовується для стислості коду.
висновок
Висловлюю подяку за рецензування статті експерту Microsoft Адаму Тьюліперу (Adam Tuliper).