История создания Complex Fracture или как я делал проект для индиджем, с какими проблемами столкнулся и как их преодолел
Приветствую, уважаемая аудшитория DTF. Сегодня я хочу рассказать историю того, как я (практически абсолютный новичок в геймдеве) работал над своим проектом и достиг, надеюсь не только по-своему, но и по-вашему мнению хорошего результата. Это история о том как во множестве раз сходились звезды (да не просто сходились, а целый парад устроили) для того, чтобы моя работа, вместе с работами остальных участников присутствовала в почётном списке завершённый проектов (а может и проектов-победителей?! Чем черт не шутит?!). Я расскажу как родилась идея проекта, какими играми и фильмами я вдохновлялся, какой была оригинальная идея и что пришлось убрать/изменить, и что в итоге получилось (хотя вы и сами видите).
Почему джем закончился а я пишу этот пост?
- Я обещал,
- Процесс доставляет мне удовольствие,
- Самореклама лишней не бывает 😉.
О том, как родилась идея
В одно прекрасное майское утро мы женой на пробежке обсуждали рынок мобильных приложений и игр, а так же ивенты и митапы , которые хотелось бы посетить. Я в очередной раз выказал желание заглянуть на какую-нибудь игровую конференциею. На что получил ответ, что для посещения такой конференции неплохо бы было что-нибудь с собой принести (то есть свой проект) и кому-нибудь показать чтобы конференция была полезной (то есть получить фидбек, найти команду, допишите все что сможете придумать).
Естественно для того, чтобы было что показывать нужно что-то сделать и мы стали обсуждать идеи (ну как обсуждать? Я предлагал, а жена просто фильтровала идеи). Мы понимали две вещи: 1 - не нужно гнаться за трендами, так как к завершению проекта тренд, скорее всего, закончится; 2 - казуалку или пазл делать не хочется (конкуренций слишком большая да и не те это проекты, которыми хотелось бы заниматься). Также мы понимали, что так или иначе мода циклична - старые добрые RPG снова набирают популярность (Divinity Original Sin, Pillars of eternity - примеры из игр (похожих на Baldurs Gate, которая вышла около 20-им лет назад, а широкие джинсы как в 80-ых и 90-ых на девушках - пример из одежды). Следовательно можно попытать счастье взяв что-то старое и переделав на новый лад, то есть: подкрутить графику, добавить сохранения и будет новый интересный продукт.
В начале или больше всего хотелось сделать какую-нибудь TBS или ARPG в стиле Dark Fantasy вроде Disciples или Diablo. Но, такой уровень и количество арта я пока, к сожалению, не осилю. Так ещё и жанр TBS как и другие стратегии не сильно популярен. Таким образом решили посмотреть на что-нибудь по-проще в реализации.
Я решил заглянуть в ещё более ранний период, в игры для возьми- шестнадцати- би них консолей. Тем более, что я иногда поигрываю на сайтах вроде oldgamesshelf в игры для старой доброй nes (моя любимая - battle toads and double dragon, которую я кстати так и не осилил 🤣). И на основе своих предпочтений у меня появилось предположение - если сделать Beat Em Up, то он вполне может сойти за свежую и оригинальную идею. К тому же мне кажется, что многим, кто не застал времена NES или других приставок, которые сразу продавались с двумя контроллерами могла бы понравиться атмосфера когда у тебя дома сидит пол-двора и все по очереди парами играют на одном экране (не сплит скрин, а когда реально одна игровая камера и экранное пространство на двоих) и проходят игру по очереди на двух контроллерах или клавиатуре, подключенной к одному устройству. А залепить ногой в затылок другу и испортить тем самым прохождение уровня, и, уже в реальной жизни залепить ему в ухо со словами "Какого хрена ты мне под удар лезешь!?" - вообще бесценный опыт 😆!
А через несколько дней (буквально 9-го мая) я прочитал про #индиджем . Звезды сошлись в первый раз...
Сам джем
Начало
Итак у меня появилась идея для проекта и сразу же возможность ее проверить. Естественно я сразу заявил о своём участии, загрузил Unreal Engine, купил на Udemy курс Бена Тристема за 10$ (как раз была распродажа, звезды сошлись во второй раз) и пошёл учиться.
Проект решено было делать в 3D, потому, что во-первых - 2D я в ряд ли столько нарисую, а во-вторых - это не очень далеко от Pixel Art’a, или вообще Pixel Art, а делать совсем как все инди мне не хотелось, да и надоел он - Pixel Art (примерно сразу после Shovel Knight).
Первые попытки взяться за работу - пробы своих сил
Примерно две недели я смотрел видеокурс и больше ничего не делал, а проект должен был продвигаться, тем более, что многие участники уже начали писать посты-обновления о статусе своих проектах. Тогда я решил переключиться на арт чтобы напомнить о себе и показать хоть какой-то прогресс.
Порисовав часа 3, я понял, что материалом (то есть CG) я владею слабо и работа займёт слишком много времени, а карандашную или акварельную работу выкладывать будет, как минимум, странно. Таким образом идея подать сюжет в виде комикса отправилась в мусорную корзину, а я приступил хотя бы к наброскам персонажа и сюжета.
Набросок персонажа, как и сюжет не вызвали энтузиазма у читателей. В общем я на это и не рассчитывал; главное, что я напомнил о себе. Нужно было продолжать работу...
Первые шаги в проекте
Поняв, что сюжет будет подаваться текстом, так как рисовать такое количество арта, какое нужно для моего проекта, я не могу, а делать арт в Blender (то есть в 3D) самому будет ещё дольше - я решил: мой проект будет прототипом на кубах и других простейших геометрических формах и примитивах. В конце концов даже Naughty Dog сначала прототипируют на кубах, а потом, если в прототип играть весело, делают под него арт.
Работа с анимациями
Решение принято - нужно продвигаться дальше. Кубы кубами, а, как минимум персонаж и пару анимаций для прототипа нужны. А где их искать? Правильно! Mixamo. Для того, чтобы прототип выглядел style consistent я скачал mesh YBot’а, скачал несколько анимаций ближнего боя и приступил к настройке. Тут мне очень помогла запись life stream’а от epic, в котором инструктор Wes Bun очень последовательно и доходчиво объяснил как настроить animation blueprint, blend spaces и даже animation montage. Также я посмотрел серию коротких туториалов по skeleton assets, но в данном случае они мне не пригодились (зато позже эти знания сделали возможным использование персонажа, которого вы сейчас можете видеть в игре, но об этом позже).
Я настроил анимации ходьбы, бега, переходы между ними и даже отдельные удары (руками), но когда начал добавлять атаку в прыжке или с разбега наткнулся на проблему - mesh персонажа вылетает за пределы капсулы. Немного погуглив я нашёл решение своей проблемы - статью о root motion, и сразу же новую проблему - у скелетов персонажей Mixamo нет Root кости и включение Root Motion для них приводит к очень странным результатам.
Решение проблем анимаций Mixamo
На данном этапе уже были жалко выбрасывать проделанную работу - нужно было искать решение. И я нашёл его в виде плагина для Blender, который позволяет добавить Root кость к скелету и переименовать все кости в иерархии так чтобы они соответствовали конвенции именования костей в Unreal Engine. Как им пользоваться можно посмотреть здесь - очень полезный ролик, но акцент мне очень сильно резал уши.
В принципе - на этом можно было остановиться. Но я просматривал очень много анимаций, так как любой проект, который является производным от файтинга должен содержать в себе очень много анимаций. Поточному манипуляции с анимациями приходилось повторять по 10-20 раз, так что это было не только не удобно, но еще и очень долго (сам плагин работает не очень быстро).
И я нашел более простой способ: загрузить только что обработанного персонажа обратно в Mixamo. Mixamo легко подхватывает иерархию костей и теперь вы можете загружать нужные анимации с уже заранее готовой иерархией костей и, самое главное, с root костью, что позволит включить нам Root Motion если необходимо.
Естественно, это не решило все мои проблемы: часть интересных анимаций я в игру так и не смог добавить, так как нужно было использовать несколько другие техники для корректного проигрывания анимаций и корректного следования капсулы персонажа за анимируемым мешем.
Так что я потратил еще какое-то время на подборку относительно простых и не имеющих странных эффектов анимаций (хотя даже сейчас вы можете заметить некоторые баги, если конечно будете из искать) и продолжил работу.
Боевая система и реакция на удары
Анимация настроена, следующим шагом было добавление реакции на столкновения атакующего и атакуемого. Для этого я добавил по капсуле на верхние и нижние конечности, а при спавне объекта на сцене (aka ConstructionScript и OnBeginPlay в Blueptins) закрепил их за соответствующими костями.
После написания соответствующих скриптов я сделал гифку и отчитался о проделанной работе. То есть, по сути, просто рассказал о своих впечатлениях о первых неделях знакомства с Unreal Engine.
Выглядело все неплохо, за исключением некоторых багов, а именно: бесконтактный бой (иногда можно было ударить на расстоянии, герой спотыкался об трубы и умирал, а также удары засчитывались до кульминационной точки анимации).
Тут на помощь пришла небольшая серия туториалов о skeletal assets, о которой я говорил выше и еще одна серия из которых, из которых я узнаю про Anim Montages и Anim Notifiers.
Сказано - сделано: после настройки Anim Notifiers баги стали проявляться заметно реже (я думал можно ли в качестве объектов для боевых коллизий использовать Physics Asset, но пока не искал по этому поводу информацию, так как неумолимое течение времени заставляло двигаться вперед). На этом создание боевой системы можно было считать законченной.
Настройка ИИ
Далее следовало сделать ИИ, так как гифки хоть уже и смотрятся довольно динамично, но избивать манекены в ряд ли можно назвать интересным занятием - нет вызова.
Узнав из документации о существовании AIController (и больше не о чем 😆) я написал несколько команд, которые друг за другом поочередно вызывались. Это были команды патрулирования и движения к игроку, а по достижении позиции игрока - атаки. Естественно я захотел сделать что-то вроде зрения и реализовал это дополнительными SphereCollision. Вы можете посмотреть ниже как выглядела сцена и персонажи.
Да, ребята, на языке хоть немного разбирающихся в Unreal Enigne это был ...ец (остальные буквы вставляем в зависимости от уровня своего воспитания). Мало того, что это ужасно криво работало, так еще и ломало всю боевую систему (удар засчитывался при контакте с, так называемой, сферой для "зрения").
Не трудно догадаться, что я выкинул все в корзину и пошел читать документацию и официальные туториалы, где и нашел вот это потрясающее видео, рассказывающее про основы AIController, Blackboards, Nav Mesh Volumes и так далее. Еще помогла вот эта статья для добавления AI Perception (то есть зрения для противников).
Немного поработав я добился примерно того, чего хотел добиться от AI - от относительно исправно патрулировал, догонял и атаковал игрока. Осталось пару моментов, которые хотелось бы поправить:
Я думал, что буду разбираться с этой проблемой неделю, если не меньше, кроме того, когда у игрока включается RagDoll послу удара противника мне тоже хотелось ограничить физику двумя степенями свободы (не будет же игрок с одного удара умирать). Два запроса в google и на картинках вы сами видите насколько я ошибался в оценках сроков реализации этой фичи 😊
Хотелось смеяться (с себя), но я сжал зубы и продолжил работу (веда у меня освободилась целая неделя), тем более, что после гифки, вернее нескольких гифок, вот в этом посте у меня начали спрашивать про графику (наверное никто не любит играть в совсем сырые прототипы).
Как я графику завозил
Кто еще не забыл - больше всего я вдохновлялся игрой Battle Toads And Double Dragon для NES, а это Sci-Fi сеттинг (с натяжкой), и мне хотелось сделать что-нибудь такое (тем более, что боты к этому располагают, а других персонажей я найти и не мечтал).
Создание уровня
А где искать ресурсы для таких целей когда у вас нет времени делать все это самостоятельно? Правильно! В asset-stor'ах. И, о чудо! Modular SciFi Season 1 Starter Bundle - Free for this month (июнь). Да это же просто чудо какое-то, это уже не звезды сошлись в третий раз - это уже какой-то парад планет в мою честь (на заметку начиняющим UE разработчикам - всегда забирайте бесплатные ассеты, они вам могут пригодиться в самый неожиданный момент)!
Да, последующую неделю я проектировал уровень.
Персонаж
Когда уровень был готов я подумал (а ведь с ботом, хотя бы в главной роли, наверное - не очень хорошо смотрится), что и подтвердил первый же знакомый, которому я показал вот эту гифку.
Грустить, как всегда, времени не было, хотя перспектива найти что-то, что удачно подойдет под визуальный стиль выглядела отнюдь не радужной (персонажи из того-же Mixamo мне совсем не нравились). И тут меня осенило - Paragon! Если кто еще не в курсе - в 2018-ом году Epic Games предоставила все ассеты Paragon для бесплатного использования любым проектам на Unreal Engine.
Я пошел искать, вдруг там что-нибудь интересное найду (еще я надеялся, что скелеты персонажей будут подходить под то, что по-умолчанию установлена в Project Templat'ах самого Unreal Engine - то есть они подойдут с ходу). И, даже как то неловко во второй раз писать. О чудо! Персонаж, хотя бы отдаленно, но напоминающий начальный концепт (правда только металлическими руками), да еще и анимированный, да еще и со скелетом правильным - звезды сошлись уже в четвертый раз (наверное я их властелин 🤣).
А с персонажем возникли проблемы...
Скелет не очень подходил под мои анимации
Да, не смотря на то, что конвенция именования костей совпадала с принятой в Unreal Engine, была маленькая проблема: просто дофигище лишних костей для оружия, каких-то эффектов, симуляции одежды и одни Epic знают чего еще.
Но, конечно я не отчаивался. Я уже посмотрел серию видео о Skeleton Assets, которое мне в самом начале не пригодилось, и знал, что есть выход из моей ситуации и имя ему - Retargeting.
Повторяю последовательность действий из туториала и вуаля: Twinblast уже бьет ногами и руками, прыгает и вообще делает все, что я захочу 😊.
Осталось решить 2 маленькие проблемы: 1 - спрятать оружие, которе летает вокруг него как огненные шары вокруг принца Келя (да, в переводе от 1С его звали именно Кель, а не Кель'Тас) из Warcraft 3; 2 - Подкрасить персонажа чтобы его вид больше подходил под цветовую схему уровня.
Сказано - сделано. Первая проблема решилась поиском нужных костей и вызовом для них функции Hide Bone By Name, а вторая - просто заменой материалов на материалы других скинов этого же персонажа. Так получился персонаж, которого вы видите в игре - руки от скина Action Hero, костюм - от скина Electro (только сияние с переделано с бирюзового на белое, опять же - в целях сохранения единой цветовой гаммы на уровне), а все остальное - скин по-умолчанию.
К сожалению, на это работа с персонажем не завершилась...
Проблемы с физикой
Я сохранил персонажа, заменил им mesh персонажа игрока и возрадовался - все красиво. Но, первый же удар по персонажу выдал новую проблему. Конечности растягивались и скручивались, как будто они были сделаны из ткани.
Ответы в google на похожие вопросы не радовали - люди предполагали что риг персонажа не очень качественный (Ога - в персонажа вложено тыщ двести доларав, и риг кривой - у кого угодно, толко не у него, просто не верится).
И правильно, что не поверил - на форумах Enreal кто-то предположил, что проблема может быть в неправильно настроено Physics Asset. И я решил заглянуть туда.
Действительно: у персонажа было несколько Physics Asset и ни один не подходил под структуру Ragdoll, которая мне требовалась (в Paragon это просто не было нужно). Пришлось снова лезть в интернет и искать информацию о том как же все правильно настроить. Конкретно мне помогло вот это видео и немного практики (то есть добавлений/удалений constraint'ов и physics body методом проб и ошибок).
Сюжет
Когда графика и боевика была готова настало время взяться за сюжет.
В самом начале проект хотелось сделать в виде шутки: пафосное название (которое я бы и не придумал, если бы мне не подсказали его в комментарии к одной из моих статей), брутальный мужлан (например как главный герой фильма Кобра, да фильм с Сильвестром Сталлоне 1986го года ) - главный персонаж и абсолютно тупой и бредовый сюжет.
Первоначально сценарий выглядел так:
"Главный герой вместе с отрядом военных атакует вражескую базу (наверное инопланетян) и попадает в плен. Там над ним проводят опыты, где отрезают руки и ноги, заменяя их протезами для улучшения боевых качеств. Персонаж стойко все терпит, хотя видит на экране в лаборатории суть каждого опыта. Но во время атаки базы, на которой все это происходит, случается поломка и лабораторный персонал переключается на экстренную починку какой-то поломки. Естественно процесс починки выводится на экран, но так как экран повернули, главный герой видит только силуэты. И ему начинает казаться, что ему хотят вживить в зонд (да, как в South Park). И в этот момент главный герой решает, что лучше сбежать или погибнуть. Он изо всех сил разрывает сковывающие его путы и на этом моменте начинается игра... ."
Но, за время работы над проектом я понял две вещи: 1) как я уже писал выше - я просто не смогу подать историю даже в виде комикса (а по-другому будет не смешно); 2) я полюбил свой проект (как говорят англоязычные люди - It's my Child!) и мне перехотелось превращать проект в шутку пусть даже и не смешную.
Я написал небольшой текст вначале, чтобы дать смысл всего движения и в конце, последний текст и будет объяснять что вообще происходит и чем была игра на самом деле. Мне такой вариант показался наиболее простым способом подогнать проект под тему конкурса.
Звук
Признаюсь - о звуке я думал в последнюю очередь, так как только в последний момент вспомнил, что вообще-то он позволяет дать дополнительный фидбек и в целом увеличить погружение.
И снова погрузился в поиск. Звуки я искал на сайтах soundbible.com (тут я нашел звуки активностей, то есть ударов, шагов, замахов) и freesound.org (а тут нашел звуки окружения).
Встроить звуки драк было не сложно - просто при проигрывай каждой анимации я проигрывал и звук. А вот со звуками окружения оказалось сложнее. Для того, чтобы было веселее я добавил много мелких объектов, которые можно пинать, ронять, падать на них и так далее (считаю, что это делает игру веселее). Но вот при проигрывании звука при ударе такого объекта обо что-либо появились трудности.
Так как практически каждый кадр регистрировалось физическое взаимодействие и все звуки сливались в непонятный шум. Эта проблема была решена расчетом силы удара при которой объект должен издавать звук и ограничением количества звуков, которые может издать объект при ударе (чтобы объект, который застрял, не бесил своими звуками, когда вы уже ушли от него на много метров).
Была еще одна маленькая проблема: при проигрывании слишком большого количества звуков фоновая музыка все время прерывалась и начиналась заново. Эту проблему я решил установкой Priority в Sound Cue, которую создал для фоновой музыки.
Мотивация решений, которые могут показаться странными
Сделать чтобы игра была не тем чем кажется с начала было я в начале хотел через смену механики: мне хотелось, чтобы у некоторых персонажей было огнестрельное оружие и при выбивании его и, соответственно, поднятии его игроком игра превращалась из Beat Em Up в Shoot Em Up как Contra. Но для реализации механики стрельбы потребовалось много времени.
Идея добавить платформы казалось бредовой, потому, что все сайд-скроллеры в том или ином роде еще и платформеры, поэтому весь сюрприз пришлось перенести в сюжет.
Решения левел дизайна
Так как уровень разрабатывался чуть ли не в самом конце - пришлось принять несколько возможно не очень логичных решений.
Персонаж умеет прыгать довольно высоко, а на уровне очень низкий потолок, поэтому пришлось нагромоздить в одной из комнат баррикады из столов и поставить на верх врага просто для того, чтобы игрок хотя бы один раз смог попробовать механику атаки в прыжке.
Теперь об управлении
Движение назад / вперед - клавиши A/D от WASD - тут все понятно, Space - прыжок тоже, атака на Enter - мне показалось, что не очень логично переносить ее на мышку. А вот бег через двойное нажатие и удерживание клавиши A или D я сделал намеренно, так как при атаке во время бега персонаж ударяет ногой, что сразу убивает противника и если бежать с зажатым Shift'om - игру будет пройти слишком просто (все будут умирать от одного удара), а так игрок будет применять и атаки руками (то есть из ходьбы).
Размер собранной игры
В первый раз когда я собирал проект я подозревал, что билд будет большим (все таки ассеты не маленькие), но не подозревал, что настолько 5.5 GB. Повезло: документация по этой теме есть и она довольна понятная и реально помогает упаковать билд поменьше. Почитав вот эту страничку я смог добиться размера в 1.3 GB - уже хлеб. Это конечно все равно снижает вероятность того, что кто-нибудь захочет загрузить проект (подозревал, что проекты большинства участников будут иметь на выходе не больше 500МБ и, по-моему, не ошибся), но, по крайней мере, не снижал вероятность загрузки до нуля.
О самой сборке проекта, то есть о остросюжетном фильме под названием "Собери билд без нужного для этого компьютера" читайте в следующем абзаце 😊.
Самая большая драма
Воскресение 7е июля - пора сдавать работы. И тут я с ужасом узнаю, что на моей платформе Unreal Engine НЕ МОЖЕТ СДЕЛАТЬ БИЛД для windows! (Unity, я люблю тебя). Чтобы оценить масштабы проблемы просто посмотрите разбивку по количеству игроков на каждой десктопной ОС. Стоит отметить, что за два дня до этого я уже делал сборку, но это было на компьютере знакомого, которому я хотел показать результаты своей работы, а поэтому я не подозревал о возможной проблеме.
Я поднимаю виртуальную машину в надежде, что Parallels позволит мне собрать билд хоть на нем, но нет.
Я в панике ищу у кого бы можно собрать проект в .exe. Мне повезло, с минуты на минуту ко жене в гости должна была зайти ее одноклассница чтобы я помог ей заполнить декларацию (естественно со своим компьютером). Я сразу прошу помочь мне с билдом (благо компьютер мощный и без труда запускает Unreal Editor). И снова неприятность...
Я жду уже около часа, прогресс бар ползет со скоростью улитки. Я нервничаю, ведь еще ролик делать (а я вообще без понятия как это делать, так как последний ролик я монтировал в Movie Maker году так в 2007-ом).
Но билд таки собирается, упаковывается в архив и отправляется в Dropbox и Google Drive. Я начинаю монтировать ролик (не хочу вам об этом рассказывать чтобы не портить психику, в первую очередь себе 😆), пишу пост, и когда все готово - нажимаю кнопку, и с чувством выполненного долга делаю глубокий выдох (время на часах 23:52).
Решаю посмотреть что там у нас по тегу #индиджем . И, как вы уже наверное догадались, моего поста там нет 🤣. Я ищу - где же он? Что не так? Может я что-то не то нажал? Может еще открыта вкладка? Нет! Все зря. Тогда я за пишу посту только название, прикрепляю билд и выкидываю в таком виде: Заголовок, скриншот и билд. Ура! Я успел - время 23:56. Теперь жму кнопку "Редактировать" и добавляю все необходимые материалы уже без спешки.
Спустя пару дней пост я все таки нашел.
Итог
Было проделано много работы, я получил огромное удовольствие от процесса и еще больше от результата (если бы мне кто-нибудь 2 месяца назад сказал что я сделаю то, что я сделал - не поверил бы). Процесс создания игры оказался настолько увлекательным, что все время, пока я работал над игрой я даже моргать забывал (из-за чего у меня очень краснели глаза).
Я очень рад, что смог поучаствовать в джеме и закончить работу. Что касается моей игры - я буду доводить прототип до ума и тестировать чтобы понять стоит ли им заниматься дальше (надеюсь, что стоит - всю жизнь мечтаю связать свою карьеру с разработкой игр).
Если хотите можете подписаться на мой твиттер (собирался вести его на английском языке, но руки не доходят), а лучше следите за проектом прямо здесь - говорят тут можно будет блог вести. Скоро создам группу в вк если будет такая потребность.
На этом я благодарю вас за прочтение и желаю удачи. Делайте игры, играйте в игры, и пусть вам везет так как мне.
P.S.
Еще раз ссылки, по которым я обучался Unreal Engine
- Character Animation in UE4 - отличный стрим, в котором рассказывается как настроить Animation Blueprint
- Skeletal Assets - Серия видео о том, что такое Skeletal Assets, как они взаимодействуют с анимацией
- 3rd Person tutorial - серия видео на закрепление предыдущих двух тем
- Unreal Engine - Physics Asset Set Up - настройка Physics Body помогла для правильной настройки RagDoll
- Basics of AI | Live Training | Unreal Engine - Запись стрима о том как сделать простейший ИИ в Unreal Engine
- Unreal Engine 4 Tutorial: Artificial Intelligence - Почти тоже самое, что и выше, только текстом + рассказывается как дать ИИ зрение
- Reducing Packaged Game Size - О том, как упаковать проект, чтобы он не занимал половину вашего жесткого диска.