Привет, Хабр!
Я прочитал статью Migrating away from Rust и хочу поделиться с вами своими мыслями, заодно переведя оригинал. Я буду вести повествование от своего лица, поскольку это скорее реакция и размышления, а не традиционный перевод.
Для меня тема весьма актуальна, так как я сам нахожусь в этом странном лагере разработки игр на нишевых движках. Я использую не Rust+Bevy, а Go+Ebitengine, но многие плюсы и минусы этих комбинаций интересно рассматривать как дополняющие друг друга.
Когда-нибудь, я обязательно напишу статью о своём опыте серьёзной разработки игр на Go, но пока я слишком сильно завертелся в рабочем процессе, чтобы успеть доделать демку своей игры до Steam Next Fest. Будет ли эта статья положительная, или это будет миграция на Godot? Кто знает!
Ну а пока, погнали разбирать статью.
Контекст
- Разрабатываемая ими игра — Architect of Rain
- Разработка стартовала в декабре 2023
- Судя по всему, игру на Rust они делали больше года
- Переход на Unity прозошёл в 2025
- Судя по всему, игру полностью переписали на C# за 6 недель (?!)
- Разработка на Unity идёт около 3 месяцев на момент выхода их статьи
Почему изначально был выбран Bevy?
- Выбор движка Bevy был обусловлен любовью к Rust
- В движке очень хороший, нативный ECS
- Хорошее и позитивное сообщество (прямо как у нас в Ebitengine!)
В сообществе разработки игр на Go часто поглядывают на ECS из Bevy. Пока ничего такого же воспроизвести не смогли, но лучшие умы уже работают над этим
Bevy — хороший
Сочетание отличной системы типов и ECS, видимо, делает рефакторинг очень удобным и надежным (видимо, меньше багов будет появляться).
Два этих компонента по отдельности всегда известны своей помощью в рефакторинге: Rust компилятор очень педантичен и не даст бесплатно и без СМС отстрелить себе ногу, а ECS разделяет объекты на множество (почти) независимых компонентов. В совокупности ожидаю, что это хорошее комбо, но есть и обратная сторона медали — рефакторинг на Rust может и надежный, но некоторые виды реорганизации кода и времени жизни объектов могут усложнить сам процесс переписывания кода.
Из того, что ещё могу выделить — это вайб сообщества, потому что я испытываю подобное в Ebitengine. Так как экосистема скорее догоняющая и в ней не всё достигло качества для продакшена, ваш личный вклад будет восприниматься более значительным. Вы можете создавать новые библиотеки, которые будут полезны другим, оставлять обратную связь и баг-репорты для других разработчиков, и просто тесно общаться с сообществом. Это ощущается как тесная тусовка, где люди друг друга знают.
Я горжусь своими библиотеками для воспроизведения XM-треков прямо в игре, поиска пути, работы с пользовательским вводом, и многими другими. Я так же стараюсь вносить свой вклад в ebitenui, хоть этот вклад и ограничивается обратной связью и репортом багов.
Я тут привёл не всё положительное из статьи, просто потому что не могу до конца оценить другие доводы. Читайте оригинал.
Bevy — плохой
Какие проблемы выделяет автор:
- Коллаборация сложная, потому что порог входа в Rust+Bevy высокий
- Конфликт детализации типизации с желанием "фигачить" игровую логику
- Быстрое развитие Bevy — каждый апдейт что-то привносит и может что-то сломать
- Нейронки хуже подсказывают по Rust+Bevy, чем по какому-нибудь C#+Unity
- Трудности интеграции моддинга
Пункт с быстрым развитием движка довольно загадочный — почему бы не обновляться в рамках одной игры или хотя бы не ограничить обновления до "не чаще раза в год"? Вернёмся к этому ниже.
Update: мне подсказали, что, возможно, проблема в устаревающих примерах и туториалах. Вот это уже проще понять, такая проблема действительно демотивирует и будет очень сильно мешать. Причём не только новичкам, которые теряют материалы для обучения, но и для опытных, так как старые библиотеки могут сломаться (и чинить их может быть некому).
Вот пример кода, который приводится как избыточная многословность:
В целом, такова попытки все ECS-запросы явно параметризировать через генерики. Основной "шум" как раз идёт от Query-типов, но что с этим делать до конца не ясно. Отчасти могли бы помочь алиасы типов.
Если разрабатывать инди игру в соло (не такая уж редкость), то коллаборация не будет критичным фактором. Но в случае Architect of Rain в команде был более молодой участник, которому было сложно осваивать эту комбинацию. Забегая вперёд, на Unity ему было проще.
Пункт с нейронками актуален и для Go+Ebitengine. Особенно если вы попросите Chat GPT написать шейдер на кастомном языке Kage… Приходится запрашивать шейдеры на GLSL, а потом уже вручную их портировать на Kage. Я какое-то время разрабатывал автоматический транслятор GLSL->Kage, но потом забил. Может, ещё вернусь к этому проекту.
Любопытно, что весь этот пункт был бы гораздо менее весомым года два назад. Туториалов конечно всё равно меньше для движков поменьше, но условный Chat GPT в разы увеличил значимость этого пункта.
С моей точки зрения, моддинг на Rust и Go к игре прикрутить примерно одинаково по сложности. Если требуется самый гибкий вариант, со скриптингом, то в обоих случаях это будет встраивание интерпретатора (Lua или ещё какого-нибудь языка). Другое дело, на сколько парадигма ECS может усложнить такое сочетание — скорее всего, моддерам захочется иметь более традиционную модель объектов, чем что-то, отражающее ECS-кишочки игры.
Вообще моддинг бывает разный. Базовый моддинг может включать в себя просто возможность добавлять новый контент в игру, ребалансить существующий, то есть работать с контентом. Например, если игра даёт свободно редактировать и добавлять какие-нибудь JSON-файлы, описывающие сущности, то моддить будет удобно. В какой-нибудь RPG через внешние файлы могут описываться предметы и способности: для игры не будет разницы, кто редактировал или создавал эти файлы — моддер или изначальный разработчик игры. Такому виду моддинга вообще всё равно, на чём вы делаете свою игру.
Здесь могло влиять отсутствие достаточного опыта с Rust и Bevy у членов команды. Чтобы эффективно делать игры на нишевых движках, нужно довольно много времени вложить в их освоение, собирание своей коллекции библиотек, и только после этого они могут быть хотя бы немного сопоставимы для создания игр против меинстримовых движков.
По моему опыту, в геймджемах типа Ludum Dare не так сильно ощущается разрыв между играми, созданными на условном Bevy и Unity, особенно если брать только 2D. Это к тому, что при наличии навыка даже в краткие сроки можно создавать хорошие прототипы, нет никакого бесплатного x100 буста, который даёт Unity, из-за которого с ним невозможно соревноваться.
Самым главным в соло разработке инди игр я считаю не движок, а ваше умение минимизировать скоуп игры так, чтобы работы было в 10 раз меньше, но игра при этом осталась концентрированным фаном для игрока. Даже повторяя это здесь, я понимаю, что сам иногда нарушаю это правило, но я пытаюсь возвращать себя в реальность и режу фичи (как уже сделанные, так и из TODO-списка).
Переход на Unity
Командой автора рассматривались следующие движки:
- Unreal Engine
- Unity
- Godot
- Движок собственного приготовления
К Unity было отторжение (особенно из-за драмы последних лет), но они решили дать ему шанс.
План проверки движков был такой:
- Выбираются несколько ключевых аспектов игры (10% игры с 90% важности)
- Потом они портируются на новый движок
- На каждый аспект выделяется не более 3 недель
Ключевые аспекты, которые они выбрали:
- Тайловая карта
- Персонажи (скелетная анимация)
- GUI
То есть, в сумме ожидалось дать на эксперимент около 9 недель.
На их удивление, им потребовалось всего 3 дня на реализацию всего этого на Unity, вместо ~9 недель!
Поработав ещё несколько дней над этим же портом, они решили остановить свой выбор на Unity. Если я правильно понял, примерно за 6 недель они закончили портирование. Что более важно — код стал менее многословным.
Переписать игру — не равно написать игру с нуля игру. Если бы они делали игру с нуля, то могло бы уйти пол года или даже больше.
Размер кодовой базы уменьшился в ~4 раза, с 64700 строк на Rust до 17000 строк на C#. Опять же, часть эффекта может быть связана с переосмыслением кода, но авторы подчёркивают, что в основном ушёл "ECS boilerplate".
Отдельно указывается, что теперь они перестали бояться обновлений движка и задышали спокойно. Интересно, а можно ли в Rust было не обновлять Bevy и жить на той же версии вплоть до релиза игры? Лично я далеко не на каждом релизе Ebitengine поднимаю версию зависимостей.
Заключение
Пожелаем удачи ребятам доделать их игру Architect of Rain.
Есть вероятность, что они перегорели после года разработки и им нужно было как-то встряхнуться — переписывание может дать такой эффект, но это очень рискованный ход. Не успей за год-два они доделать свою игру уже на Unity, может выйти ещё одна статья, Migrating away from Unity, с переходом на… Ebitengine!
Мораль сей басни такова — ожидайте, что ваших сил хватит на год-полтора. Мало кто может продуктивно работать над проектом дольше, не достигнув хотя бы какой-то вехи в виде релиза (даже если это ранний доступ в Steam).
Если вам интересно, как обстоят дела в геймдеве на Go, заходите к нам в телеграм! Мы уже успели там обсудить оригинальную статью — у нас достаточно любителей Bevy.
Напоследок, вот вам краткий гайд по старту разработки игр на Ebitengine:
https://www.quasilyte.dev/ebiten/ru/
Хотите как-то сказать мне спасибо или просто сделать приятно? :D
Добавьте мою игру в список желаемого (wishlist). Я разрабатываю её на Ebitengine и планирую выложить исходники после релиза (а пока можете поизучать исходники моей прошлой крупной игры — Roboden).