Дневники разработки Chrysalis: Chrome Butterfly
Как мы взяли ААА-архитектуру и две недели сражались с legacy-кодом
Рассказываю, почему мы решили делать наш нуарный детектив на базе готовой архитектуры Epic Games, и как старый синтаксис из UE4 может превратить сборку проекта в ад. И при чем тут жара в 40 градусов.
Привет, DTF!
Меня зовут Макс, я лидер, визионер и вдохновитель небольшой, но очень амбициозной команды — Gravity Vector Studio.
С чего все началось?
В 2024 году наша команда, влюбленная в жанр RPG, космос и хорошую научную фантастику собралась вокруг крупного sci-fi проекта The 3 Body Problem (T3BP) — это был масштабный эксперимент, где мы проверяли себя в архитектуре, дизайне и системах на Unreal Engine. Тогда мы ещё не понимали, насколько глубоко этот опыт нас изменит (забегая вперед: T3BP по-прежнему остается в разработке).
Сегодня я расскажу не о T3BP, а о проекте, который стал его «обратной стороной» — о Chrysalis: Chrome Butterfly, неоновом нуар-детективе с элементами шутера и философским подтекстом, где кинематограф встречается с инженерией.
История рождения Chrysalis: Chrome Butterfly (рабочее название GVSL) началась с того, что накопленный опыт заставил сказать себе: "Хватит долгостроев!" и было принято решение сделать что-то более сфокусированное, но не менее амбициозное.
Сеттинг вдохновлён фильмами вроде John Wick, Ghost in the Shell и Blade Runner, а геймплей сочетает детективную слежку, стелс и стильный боевой режим с замедлением времени.
Мы решили вложить в разработку новой игры весь наш опыт, лучшие идеи и наработки, чтобы выпустить демо-версию прямиком в Steam этой осенью.
Фундамент на вырост: почему мы выбрали ААА-архитектуру
Первый пост — как первая сборка проекта: всё ломается, но именно с этого начинается магия. Совмещая роль тех-лида в команде, я много времени провожу в коде, занимаясь архитектурой, прототипированием на Blueprints и DevOps. И первое ключевое решение, которое нужно было принять для Chrysalis: Chrome Butterfly — на чем его строить?
Можно было бы пойти по пути геймджема: "собираем на коленке, быстро, на блюпринтах, а со спагетти разберемся потом". Но опыт разработки T3BP показал: если есть проверенное, масштабируемое решение, его нужно использовать. Даже если на старте оно кажется избыточным.
Поэтому мы взяли за основу готовую ААА-архитектуру от Epic Games. Почему?
1. Надежность: Когда твой код написан инженерами движка, есть уверенность, что он не развалится при смене версий UE.
2. Читаемость: Код эпиков — это эталон, на который можно равняться.
3. Знакомые инструменты: Все фреймворки, классы и менеджеры уже на месте.
Это как строить дом: можно начать с сарая, а потом пристраивать комнаты, а можно сразу заложить прочный фундамент. Второй путь дольше на старте, но избавляет от головной боли на релизе.
Две недели в аду компиляции
Итак, решение принято. Задача: собрать под единой архитектурой все наши наработки, плагины и системы из других проектов. Я заложил на это пару недель и… погрузился в персональный ад из дебага, фиксов и ночных пересборок.
Спойлер: у меня ушло около двух недель по 4-6 часов ночных бдений, чтобы пересобрать и отрефакторить более 170 классов из разных систем. Усугубляла всё это 40-градусная жара в Тбилиси, из-за которой приходилось включать кондиционер даже ночью. Иначе горячий воздух от вентиляторов ПК при компиляции превращал штаны в персональную баню.
Проблема, с которой я столкнулся, знакома многим C++ разработчикам в Unreal Engine. Имя ей — "плавающие" ошибки, вызванные legacy-кодом.
Фактически, это конфликт между устаревшими практиками написания кода (перенесенными из UE4 или ранних версий UE5) и строгими требованиями современного компилятора и Unreal Header Tool (UHT) в UE 5.5 - 5.6.
Если просто, то это работает так:
- UHT — это инструмент, который сканирует ваши C++ заголовки (.h файлы) и генерирует на их основе специальный код (.gen.cpp файлы), который "дружит" ваш код с Blueprints и редактором.
- Холодная сборка (полная) — UHT пересоздает все эти файлы с нуля.
- Горячая сборка (быстрая, инкрементальная) — UHT пытается обновить только то, что изменилось.
Проблема в том, что старый синтаксис, который раньше "прощался" движком, теперь вызывает ошибки. Но из-за кэширования они могут появляться только при холодной сборке, в то время как в редакторе (где сборка всегда горячая) всё может выглядеть нормально. Это и есть "плавающая" ошибка — билд валится, а ты не понимаешь почему.
Вот несколько примеров "legacy-кода", который раньше работал, а теперь вызывает боль:
1. Небезопасные приведения типов:
2. Неинициализированные умные указатели (TObjectPtr):
Раньше код был полон "сырых" указателей (`ACharacter*`), которые могли быть `nullptr`. Теперь движок требует явной инициализации умных указателей и проверок `IsValid()`.
3. Устаревшие API и типы данных:
Это лишь вершина айсберга. По сути, наши добрые инженеры из Epic Games так сильно переработали API движка, что код, который отлично работал в UE 5.1- 5.4.4, теперь требует серьезного рефакторинга.
Итог: крепкий фундамент для быстрого старта
Эти две недели были не просто "причесыванием" кода. Это была необходимая работа по созданию стабильного фундамента. Да, это было сложно. Да, пришлось перелопатить тонны чужого и своего старого кода.
Но результат того стоил. Теперь у нашей команды есть:
- Стабильный проект на современной архитектуре, который не боится холодных сборок.
- Быстрый старт для разработки геймплея без страха, что всё развалится.
- Отличный задел на будущее, который позволит нам легко масштабировать игру.
Спасибо, что дочитали этот лонгрид до конца! Это только начало нашего пути. Если вам интересен нуар, киберпанк и закулисье инди-разработки — подписывайтесь на наш Telegram-канал и VK - сообщество.
В следующих постах я расскажу о том, как мы создаем уникальный геймплей, смешивая шутер от третьего лица с детективными элементами расследования, и как строим мрачный мир Нео-Киото. Оставайтесь на связи!
Буду рад ответить на ваши вопросы в комментариях!