VR-игры всегда вызывали у нас восхищение. Это некое подобие магии в цифровой оболочке, полный эффект погружения в другой мир. На всех конференциях VR-проектам уделяется наибольшее внимание, масштабные стенды, сотни зрителей, ожидающих своей очереди нырнуть в свежесозданную вселенную. Так как наша компания по большей части не про развлечения, а скорее про эволюцию и прогрессивные подходы — мы детально разобрали вопрос о том, как блокчейн может быть полезен в таком молодом жанре геймдева как VR.
Ответ пришел сразу — смарт-контракты и новейший стандарт токена сети Ethereum ERC1155, предназначенный специально для создания игровых/цифровых активов. ERC1155 — токен, объединивший в себе лучшие черты популярных ERC20 и ERC721 (технические подробности можно прочитать в readme github’а репозитория). Представим себе классическую ситуацию — вы выбили редкий и дорогой предмет или скин. Как продать его так, чтобы тебя не обманул покупатель или у тебя самого отсутствовала возможность беспрепятственно забрать чужие денежки, не отдавая предмет? Правильный ответ — смарт-контракты. И ERC1155 токен — именно то, что нужно для реализации подобного функционала. Предмет может иметь свои характеристики — в виде силы, урона, стойкости, защиты, доп.урона (характерные ERC721 токену) и свою стоимость (характерную токену ERC20) в одной оболочке — разве это не звучит вдохновляюще? Все игры могут стать безопасными и удобными для хранения, передачи и продажи своих цифровых активов. Попробуем решить эту задачу на примере задуманной нами игрушки.
Концепцию мы придумали довольно быстро — аналог популярной настольной карточной игры “Манчкин”, перенесенный в VR-вселенную, со смарт-контрактами для торговли любыми выбитыми в ходе игры предметами, доспехами и оружием. Выбор технологии реализации для наших инди-разработчиков оказался делом непростым, но интересным и об этом опыте мы и хотим поведать вам ниже.
React 360
Так как у большей части команды был обширный опыт разработки на React, появилось желание попробовать React-360 для решения поставленной задачи. Описание инструмента показалось достаточно функциональным, поэтому мы сделали выбор в его сторону.
Установка и описание
Установка React-360 начинается с установки его CLI с npm, которая помогает быстро и удобно инициализировать, запускать и билдить проект из командной строки.
После инициализации проекта мы получили готовый шаблон проекта, в котором два основных файла — client.js и index.js, а также папка static_assets, где хранятся все файлы асетов для рендеринга, index.html и остальные конфигурационные файлы.
Рендеринг
Первый файл (client.js) содержит код рендеринга и работу с основным классом React360. У React360 есть два типа рендеринг-объектов — это renderToLocation, который отвечает за рендеринг 3D-объекта, и renderToSurface, который отвечает за рендеринг 2D-объекта. Также мы определили Controller для камеры, который описывает ее поведение: в нашем случае описано движение камеры (как главного героя) по нажатию определенных кнопок клавиатуры. Потом мы задали дефолтный бэкграунд для всего проекта и в последней строчке записали React360 в объект window (который является глобальным объектом для браузерных приложений).
Впоследствии, метод init из React360 вызывается в index.html файле следующим образом образом:
Во втором файле (index.js) происходит регистрация компоненты в приложении, с целью их дальнейшего использования для рендеринга в client.js файле.
Так что флоу рендеринга компоненты (объекта) выходит такой:
а) Создание в отдельном файле;
б) Регистрация в index.js;
в) Рендеринг в client.js.
Позиционирование
Следующий момент — это позиционирование объекта в 3D-плоскости. В React-360 при позиционировании, как и в рендеринге, есть различия между 3D и 2D-объектами. 3D-объекты могут быть позиционированы двумя способами.
- Через Location при рендеринге.
- Через Transform в самом объекте.
У нас выбор пал на Transform при дефолтном Location, как советует официальный сайт React-360. Translate отвечает за позиционирование в 3D плоскости.
2D-объекты позиционируются, используя систему flex, как и в React Native, что в нашем случае оказалось достаточно неудобным:
Чтобы спозиционировать кнопку справа от камеры, нужно было создать View, как в React Native, и задать ей ширину, соответствующую дистанции от крайней левой точки экрана до того места, где должен быть объект, и высоту, соответствующую дистанции от верхней точки экрана до области, где должен быть объект. Также было необходимо задать определенные стили для того, чтобы внутренний контент располагался в нижней правой точке View. В итоге это все выглядит громоздко и неудобно, проще использовать тот же translate для размещения такого рода объектов, представляя их как 3D объекты с 0 глубиной.
Импорт объектов
Следующий пункт — это импорт 3D объектов в React-360. И тут, на первый взгляд, все просто и понятно. Есть стандартный компонент Model, у которого есть props source, принимающая JS объект пути к файлам .obj (файл самого объекта) и .mtl (файл материала данного объекта):
Но и тут возникли интересные подводные камни. Суть оказалась в том, что .mtl файл имеет map текстуру по умолчанию в .tga формате и прописанный путь на диске того, кто его разрабатывал. Нам не только пришлось менять путь к файлам вручную, но и менять их на .png, так как файлы .tga формата не рендерились в браузере. Формат .png позволил нам правильно отрендерить текстуры.
Освещение
Так как система освещения в документации вообще не описана, пришлось залезть в исходники react-360 и найти там что-то касающееся Lights, а потом на примерах смотреть, кто и что делает, и как с этим зоопарком работать. Методом проб и ошибок разобрались, применили к моделям AmbientLight, SpotLight и PointLight. Их позиционирование такое же, как и у 3D объектов, но также есть и угол:
Свет к объекту так и не применился, но мы не отступили, и, путем долгих поисков и хождений по всевозможным issue в репозитории react-360, наткнулись на то, что нужно поставить props lit true, и только после этого свет начал действовать на объект.
Движение
Мы приняли главную камеру в качестве основного игрока, которым мы осуществляем движение и действия. Для этого написали Controller для камеры, где инициализировали основную функцию интерфейса:
которой передаются текущие позиция камеры и ее вращение. С ними в камере можно работать, чтобы изменять по какому-то событию, у нас таким событием было нажатие кнопок W A S D (как обычно принято), впоследствии мы хотели заменить их нажатием на клавишу и переходом в ту координату, на которой было произведено нажатие, чтобы потом заменить это на VR Controller. На сладкое задали скорость передвижения и дистанцию, с которой работали. У нас получилось движение с подергиваниями и полным отсутствием физики: шагали сквозь текстуры, вылетали за пределы и т.п. В документации физика не описана от слова “вообще” (и в принципе подобный не“game friendly” на этом этапе погружения становится привычным).
Вывод
React-360 хоть и работает с Three.js и WebGL, но совершенно не подходит для решения такого рода задач, более того, он вероятно и не предназначался для геймдева. React-360 отлично справится с трехмерными презентациями, виртуальными турами по объектам, просмотром панорам и т. д.
Но даже если вы возьметесь делать такие вещи в этом технологическом стеке, то столкнетесь с трудностью в виде плохой документации, которая заставит вас тратить часы на решение маленькой и с виду простой задачи.
Разработчик должен быть знаком с JS, желательно с React, так как тут используется JSX, а также с тонкостями стилизации моделей (включая позиционирование), и, кроме того, с паттернами разработки на React, иметь опыт работы с React Native. Другими словами - порог входа достаточно высок.
Unity
После всех мучений мы решили использовать второй инструмент в рамках наших компетенций. На этот раз выбор пал на Unity, так как в команде есть C#-разработчики.
Установка и описание
Установка происходит достаточно просто — банальным скачиванием и распаковкой дистрибутива с официального сайта. Есть одно «но»: Unity пока что работает только на Windows и Mac (с 10 версии). Поэтому нам пришлось пересесть с Ubuntu на Mac.
Так как Unity — это игровой движок, включающий в себя хороший и удобный UI, то проект создается простым кликом на кнопку, после чего ты получаешь полный шаблон необходимых файлов. В основном, все лежит в папке Assets.
Рендеринг
Так как рендерингом занимается сам движок, то и прописывать ничего не надо.
Позиционирование
С позиционированием все так же просто, как и с рендерингом. Достаточно перетащить объект в поле и работать либо с ползунками в соответствующей форме (вставить картинку), либо в удобном GUI (вставить картинку). Как и с рендерингом, ситуация такова, что ничего прописывать не потребовалось.
Импорт объектов
Простой Drag’n’Drop, изначально внутрь Asset в соответствующую папку, а затем аналогичная операция на поле GUI. Кода нет.
Освещение
Работа с освещением ведется так же просто, как и с предыдущими пунктами. Создание нового освещения происходит в соответствующей вкладке проекта. Также достаточно подробно описана система в документации.
Движение
Это первый пункт, где понадобилось что-то закодить. А именно поведение игрока и камеры во время передвижения. Для системы движения мы использовали систему NavMesh и ее Агентов. Расчертили область, где можно ходить в GUI, обозначили камеру и модель, как Агента в Navigation System. Затем создали скрипт, это делается очень просто в GUI:
- Выбирается объект;
- Нажимается кнопка Add Components;
- Выбирается New Script;
- Пишется название.
И вуаля — стандартный шаблон скрипта в корневой папке создан. Нам нужно было просто перенести его в папку Scripts и открыть (по умолчанию открывается в VS, что очень удобно). Стандартный шаблон скрипта имеет понятный интерфейс в виде двух функций:
- Start — используется при настройке компоненты;
- Update — вызывается на каждый фрейм.
В функции Start мы залочили курсор по центру экрана и записали нашу компоненту в соответствующее свойство класса, а также объявили дефолтные параметры для остальных свойств.
В функции Update мы написали логику вращения объекта за курсором, а также передвижение объекта по клику:
Вывод
Помимо достаточно очевидного вывода об удобстве Unity, хотелось бы отметить, что для того, чтобы работать на Unity можно вообще не быть программистом. У Unity великое множество туториалов для начинающих, очень простых и понятных, а также качественная, обширная документация и живое, активное комьюнити.
Источник