ИгрыХабрахабр

[Из песочницы] Наша с девушкой первая видео игра. Разработка на Unity. Часть 1

Ну как первая… Если не считать релизы только под Android и с десяток заброшенных проектов у финиша, то да, это первая наша игра с замахом больше чем одну платформу. Как же всё начиналось? А всё просто, работали мы значит над другим проектом, назовем его «проект А», работали уже долгое время и решили, а не сделать ли нам за пару месяцев игру и потренировать на ней наши маркетинговые навыки, а «проект А» выпустим сразу после с большим опытом в продвижении игр. Но звезды не сошлись, петух не свистнул и «проект А» залег на дно ровно на год. Но эта история не о нем, а о логической игре под названием «Cubicity: Slide puzzle».

В итоге наша цель была следующей, круглые фишки соединяются в заданную фигуру, перемещаясь свайпом в 4х направлениях.
По первому плану задумывалось следующее: минимум графики, минимум UI и всего что только возможно по минимуму, игра должна была быть в стиле сегодняшних казуалок, которых на рынке так же много, как и Match-3. Кто уже играл в Cubicity, тот знает, что от этой задачи мы далеко не ушли, но по остальной части совершили довольно большой скачек, как для команды состоящей всего с 2х человек.

Мы не делимся тут большим опытом или знаниями, здесь описана только история одного проекта небольшой компании. Если кто-то из читателей ожидает найти здесь секрет успешной и быстрой разработки игр, то знайте, секрета нет. Но для многих из вас, наши читатели — это послание из прошлого от самих разработчиков. Успешного или нет, нам еще не известно.

После недели раздумий, как разнообразить игру и завлечь игроков, пришла гениальная мысль… Посмотреть на Asset store кубических или круглых персонажей. Возвращаясь к истории создания Cubicity, работаем мы в основном только на Unity и стандартный набор любого уважающего себя Unity разработчика здесь: Newtonsoft.json, Zenject, Cinemachine, Dotween и т.д… Как видели выше, первый прототип игры выглядел именно так, кубы и блинчики. Такая же ситуация произошла и с блоками по которым сейчас перемещаются персонажи. Ну и понеслась, несколько паков с персонажами были куплены без раздумий. Остальное решили оставить на новые уровни и внедрять их по одному в 30-35 уровней. Также составили список новых элементов геймплея, со списка примерно в 30 новых плюшек, отобрали для начала нейтральные вещи, такие как: перенаправляющие блоки/стрелки, лифт и телепорт.

Очень много на самом деле и мы не раз об этом пожалели. Честно, не можем вспомнить, что нас побудило на первых парах сделать так много уровней, но как есть, и в первый релиз пошло 95 уровней. А потому, что игра была сырой и много чего изменялось по ходу. Почему пожалели? На все уровни ушло 2 месяца непрерывной работы. Приходилось довольно часто получать дозу «дня сурка», заходя в каждый из 95 уровней и внося изменения. В продуктивные дни, 10 уровней не составляло особого труда переместить с головы на бумагу, а после и в сцену. Это не были уже на 100% готовые уровни, но очень близко. Но были и те дни, когда чувствуешь себя Хенком Муди из Блудливой Калифорнии, переживающим творческий кризис, думаешь всё, иссяк, но наступает новый день и новые идеи.

Отрисовка как и в большинстве игр проводится во вне экранную поверхность с разрешением меньше нативного и блитится в основную поверхность, но UI для четкости и читабельности рисуется без каких либо изменений в разрешении. Если говорить про визуальную составляющую, то тут все несколько сложнее. Для сглаживания было экспериментальным путем выбрано 2x MSAA + FXAA, как те которые дают лучшую картинку при наименьших затратах ресурсов. Таким образом, мы получаем лучшее от двух миров – не размытый UI, но и не слишком прожорливый рендер в игре. Установка лимита кадров позитивно сказывается не только на потреблении энергии, но и на нагреве телефона, что в свою очередь не дает телефону тротлить из-за перегрева. Здраво рассудив, что логической игре ни к чему 60 кадров в секунду, мы решили не изобретать велосипед и установить лимит кадров в 30fps (чего уж говорить, даже консоли обычно этим занимаются).

Поскольку при каждом запуске уровня персонажи выбирались рандомно из доступных игроку, то рисовать какую либо миниатюру фигуры из персонажей было бы проблематично. Нелегкое решение ждало нас впереди, и это Finish points. Кубы на финишах не казались тогда столь жуткой идеей, и бумажная живопись помогала пройти уровень и довести каждого на свое место. Можете не верить, но именно эту задачу решали дольше всего и оттягивали на потом. Еще спустя несколько дней, этих персонажей развернули и подсветили, стало гораздо понятнее кто есть кто, но все еще не удовлетворительно. После было принято решение вместо кубов использовать тех же персонажей но поменьше, стало лучше, но только для нас. До свидания лето, скоро с тобой вновь встретимся! Окончательный вариант был принят еще через месяц, методом проб и ошибок, и еще пара недель уходит на создание иконок для финишей.

Но по факту это простейший и не очень грязный хак. На наш скромный взгляд, тучи у нас получились довольно приятными на вид. Этот подход не оправдал себя, так как для мобильных платформ желательно уместить игру в лимит размера для скачивания по LTE. Когда только решили добавить тучи, то первая мысль была, сделать задник 360 видео. Вторым желанием было написать свою систему для облаков, это было заманчиво как для разработчика, но как для человека, который хочет закончить игру поскорее это не подходило. Чтобы видео выглядело чуть лучше, чем отданное на растерзание шакалам сжатия, ему самому нужно было выделить 10-15 Мбайт, что в сочетании с наличием в игре ночных уровней со своими тучами, слишком много (весь конечный билд игры на Android занимает 61 Мб). После добавили случайные размеры между двумя константами на ряду со случайным вращением. Решение пришло в виде создания текстуры для облака и создания системы частиц с бесконечным временем жизни частицы, и также ограниченным количеством частиц в общем. Результат был более чем удовлетворительный – наше небо заполнилось облаками, которые были миловидны и не вызывали у нас желание плакать глядя на них.

Одной из причин является отсутствие мягких теней на мобильных платформах с OpenGLES 2. Тени в игре (в мобильной версии) полностью состоят из квадов, которые просто расставлены вручную, так как не хотелось добавлять реальные тени в мобильную версию. 0, ну и конечно деградация производительности на слабых устройствах.

Также к нашему процессу пост обработки добавлен AmplifyColor – отличный ассет за свои деньги, позволяющий применять разные Lut-ы на пост обработке. Как говорили ранее, для сглаживания мы использовали 2x MSAA + FXAA, но это еще не все! В процессе разработки, мы пробовали разные подходы, включая стандартный unity post processing stack, но в билде его шейдеры и варианты занимали столько, что ни в сказке сказать, ни пером описать. При правильно подобранном lut, картинка становится лучше. Огромное количество людей, до сих пор ходят с китайцем за 40$ и жалуются вам в комментах, что на их микроволновке ваш DOOM не идет). Некоторые решения были очень красивы, но работали крайне плохо на телефонах не первой свежести (поверьте, если вы думаете, что у всех сейчас хотя бы ‘нормальные’ телефоны – вы ошибаетесь.

Отбалансив, как могли одной левой ногой, решили внедрить инструменты для облегчения жизни игроку (Ход назад, Бомба, Ледяной блок, Телепорт), и да, стало жить проще, но не нам, а только будущим игрокам. Баланс игры — это всегда не просто и даже сейчас всплывают мысли, а не слишком ли сложные уровни, а не часто ли сложные уровни выпадают и т.д. У нас же работы и багов прибавилось.

И вот «На утро вышла черепаха!». Добрались к меню игры, силы и нервы на пределе, творческая натура ударила по тормозам, и не будем утаивать, пришлось вдохновляться другими играми, за что им огромное спасибо. Непрямо на следующее утро, но вышла, UI был готов по предварительно созданным макетам.

Мы решили добавить облачные сохранения и в целом не пожалели об этом. Желание быть стильным, модным, молодежным не обошло и нас. На Steam — это Steamworks, для мобильных – GooglePlay и GameRoom. Это не было самой простой задачей, так как на разных платформах, разные провайдеры облачного сохранения. Для начала мы решили использовать EasyMobile для этих целей, но увы, рано или поздно отказались от этой идеи. Так что пришлось унифицировать систему сохранения для возможности подмены для нужной платформы. Как результат выбор пал на Firebase Realtime Database и аутентификацию через Facebook. Плагин сам по себе хорош, и имеет огромное количество возможностей, но сама специфика работы с нативными облачными хранилищами нам не очень понравилась. Так же в базе есть лимиты по трафику и чтобы экономить его, мы каждый раз при записи создаем GUID и записываем его как в базу так и на устройстве. Если коротко, то пришлось пройти 7 кругов ада, чтобы это все заработало (и тут дело не в программировании, а скорей в 100500 настройках, которые нужно сделать в 100500 местах приложения и кабинетах в Facebook, Firebase и т.д.). В результате синхронизация была добавлена, но… Одним из самых странных для нас багов, было неочевидное поведение Firebase Database в некоторых случаях. Таким образом если мы видим что GUIDы на устройстве и в облаке совпадают, мы можем быть уверенными, что не нужно вычитывать все данные из облака, а можно пользоваться локальной копией данных. Так как мы используем Json, мы сериализируем классы предназначенные для хранения состояния, но Firebase иногда ведет себя несколько странно.

Если мы передаем Firebase для записи объект-словарь, например такого вида:

var dict = new Dictionary<int, SlotState> , { 1, new SlotState() }, { 2, new SlotState() };

Но не тут-то было. Когда мы будем считывать его из базы, мы получим не объект Json, а массив Json (What?)
Ну вроде, понятно, будем использовать везде списки и не будем испытывать проблем, да?

Если мы запишем в Firebase:

var dict = new Dictionary<int, SlotState> { { 0, new SlotState() }, { 1, new SlotState() }, { 100500, new SlotState() };

Или даже:

var dict = new Dictionary<int, SlotState> { { 0, new SlotState() }, { 1, null }, { 2, new SlotState() };

Когда мы будем читать его из базы, мы таки получим Json объект с ключами и значениями.

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

Этот вопрос слышали чаще всего. Когда релиз? Составить список маркетов, выбрать дату релиза, избегать крупных распродаж, довольно много нюансов, из-за которых релиз сдвинулся, как минимум на 2 месяца. Но нужно было основательно подготовиться к этому дню. Решили точно заказать обзор на 4pda, закинуть новость о игре на несколько форумов и бомбить соц.сети в частности Instagram (конечно же платно). Послушав совета одной статьи, выбрали вторник и среду для релиза. Что из всего этого сработало, мы с вами узнаем во второй части этой истории, но уже позднее.

Создать быстро игру – это не всегда быстро. Что имеем в итоге? Обзаведитесь людьми, которые смогут помочь вам дельным советом в незнакомых вам отраслях. И не исключено, что ожидаемые сроки создания игры придется умножить на 5. Негоже подбираясь к релизу быть вялой сосиской и быть менее полезным, чем на старте проекта. Расслабляйтесь при любой возможности, так как создание чего либо, не только игр, забирает много сил. А от нас, спасибо за внимание, удачи и до встречи в следующей статье. Ну и деньги, ищите деньги, они вам понадобятся.

Показать больше

Похожие публикации

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»