Розробка гри на Flutter: де ламаються проєкти
Розробка гри на Flutter майже завжди стартує швидко: сцена, спрайти, ввід, пара механік — прототип збирається за лічені дні й на топовому пристрої працює рівно.
Складнощі приходять пізніше, коли об'єктів на сцені стають сотні й з'ясовується головне: логіка та рендеринг живуть в одному потоці.
Поки він рахує фізику, колізії, спавн і анімації, на підготовку наступного кадру часу вже не залишається. На слабких пристроях це дає просідання, які видно оком: рваний рух, затримку на натискання, «залиплий» персонаж.
Гравець не розбирається в причинах — він бачить, що гра гальмує, і йде; у відгуках це повертається рейтингом і достроковими видаленнями.
Друге вузьке місце ігрового циклу — жорстка зв'язка зі сценою. Кожна нова механіка править спільні базові класи, де описані оновлення та рендеринг, і зачіпає те, що вже працювало: бонуси нараховуються двічі, збереження розходяться зі станом, рівень перестає збиратися.
Переписувати доводиться не одну сцену, а половину гри — і це вже завдання не про графіку, а про строки.
Розбираємо, як це закривається: де проходить межа між логікою та рендерингом, як укласти навантаження в бюджет кадру і чому мобільна гра на рушії, зібрана за такими правилами, витримує і потік нових механік, і пристрої з нижнього сегмента.
Що дає єдина кодова база для двох платформ
Кросплатформна мобільна гра на Flame збирається з одного дерева вихідних кодів: ігровий цикл, фізика зіткнень і шар анімацій працюють поверх Flutter і не знають, на якій платформі запущені.
Логіка рівнів, баланс, економіка та прогрес гравця живуть у спільному шарі, а відмінності — ввід, покупки всередині застосунку, сповіщення, локальне сховище — виносяться в тонкі платформенні прошарки з однаковим інтерфейсом. Такий розріз тримає розбіжності між збірками в межах одиниць відсотків замість десятків.
З погляду строків випуску оновлень це і є основний ефект. Один цикл перевірки, один набір автотестів і один розбір правок закривають обидві платформи, тому реліз готується паралельно, а не двома послідовними ітераціями.
Час збірки релізу скорочується приблизно вдвічі: важкі кроки — компіляція ядра, прогін тестів, пакування артефактів — виконуються один раз, а подвоюється лише тонкий платформенний шар.
Окремо зникає клас відмов, який найдорожче виправляти: розсинхрон версій, коли на одній платформі вже нова механіка, а на іншій ще стара, і гравці бачать різний баланс.
За єдиної кодової бази такий стан фізично неможливий — номер версії, набір рівнів і правила нарахування нагород надходять з одного джерела.
Щоб ефект не розчинявся з часом, контур збірки фіксує спільний тег версії та єдиний набір гілок, а платформенні відмінності допускаються тільки в прошарках — перевірка на рев'ю це відстежує. Тоді наступний сезон контенту додається один раз і одразу стає доступним обом аудиторіям.
Режими розробки: рушій, нативний модуль, гібрид
Вибір режиму — питання того, де потрібна продуктивність, а де важливіша швидкість змін. У режимів розробки ігор різні межі застосовності: рушій дає спільний код для двох платформ, нативний модуль — повний доступ до пристрою, гібрид намагається поєднати обидва. Нижче — що кожен закриває і де починає заважати.
| Варіант | Коли підходить | Обмеження |
|---|---|---|
| Рушій (Flame на Flutter) | Цикл гри, спрайтова анімація, фізика 2D, спільний код під обидві платформи | Обмеження ігрового рушія: важка графіка, доступ до заліза й системних сервісів — тільки через прошарок |
| Нативний модуль у грі | Камера, розпізнавання зображень, робота з периферією, доповнена реальність, розрахунки в реальному часі | Дві кодові бази, окремий темп випуску версій, спільний шар зв'язку доводиться підтримувати вручну |
| Гібридний підхід | Потрібні і спільна логіка, і повний доступ до пристрою: ядро на рушії, критичні вузли — нативні | Зростає складність підтримки: два стеки, жорсткі домовленості щодо обміну даними між шарами |
На практиці основний цикл збирають на рушії, а нативні модулі додають точково — по одному вузлу, коли заміри показують просідання. Гібридний підхід виправданий, якщо таких вузлів кілька і вони не переписуються від версії до версії.
Скільки нативних частин потрібно вам, ми оцінюємо до першого рядка коду — від цього залежить і склад команди, і порядок робіт.
Етапи роботи: від прототипу до передачі в підтримку
Етапи розробки гри — не бюрократія, а спосіб не переробляти. Помилка в схемі стану спливає на середині проєкту, а провал за частотою кадрів — уже після випуску, коли переписувати рендеринг найдорожче. Тому кожен наступний крок стартує тільки на прийнятому результаті попереднього.
- Розбір завдання й аудит коду. Якщо гра вже існує, починаємо з читання репозиторію: як влаштований ігровий цикл, де живе стан, які місця тримають кадр. На виході — карта ризиків і рішення, що переписуємо, а що залишаємо.
- Схема архітектури. Розділяємо логіку, стан, рендеринг і дані на шари, щоб новий рівень або режим не ламав решту. Схему узгоджуємо до першого рядка коду.
- Прототип ігрового циклу. Збираємо мінімальну іграбельну версію на Flutter: реакція на керування, поведінка камери, темп. Відчуття доводимо на сірих блоках, без графіки й контенту, — правки не тягнуть за собою переробку рівнів.
- Налаштування збірки й середовищ. Розводимо профілі розробки, тестування й випуску, автоматизуємо збірку й підпис — із процесу зникають ручні кроки та пов'язані з ними помилки.
- Перевірка продуктивності гри. Довгі сесії на пристроях нижнього сегмента: пам'ять, стабільність частоти кадрів, поведінка за слабкої мережі. Вузькі місця закриваємо до передачі, а не після відгуків у магазині.
- Передача проєкту. Репозиторій з історією, документація зі збірки й випуску, доступи до магазинів і аналітики, навчання команди замовника.
У кожного етапу є перевірюваний артефакт — тому проєкт не застрягає в стані «майже готово», а приймання йде без сюрпризів і повторних доопрацювань.
Артефакти проєкту: код, збірки, регламенти й документація
Передача проєкту — це не архів з вихідними кодами, а комплект, за яким інша команда інженерів зможе зібрати, випустити й доопрацювати гру без нас. Усе, що з'являється в ході роботи — включно з проєктом на Flutter, — живе в репозиторії: налаштування, конфігурації, правила. Нижче — що саме переходить замовнику і в якому вигляді.
- Вихідний код гри — повна історія змін і зафіксовані зовнішні залежності, щоб збірка відтворювалася на будь-якій машині, а не тільки в автора правки.
- Схема збірки — конфігурація конвеєра збірки: одна команда дає тестову збірку та релізну, ключі підпису зберігаються в захищеному сховищі, а не в репозиторії.
- Правила гілкування — які гілки вважаються релізними, як оформлюється правка і що перевіряється перед злиттям в основну.
- Документація проєкту — схема архітектури, опис ігрових систем, економіки та збережень, пояснення щодо нестандартних рішень.
- Регламент оновлень — порядок випуску версії: перевірки перед публікацією та робота зі зворотною сумісністю збережень у гравців.
- Інструкція з випуску — покроковий шлях від збірки до публікації в магазинах із позначками, де потрібен ручний крок.
- Політики доступу — ролі в репозиторії, права на публікацію, доступи до панелей магазинів і аналітики.
- Регламент підтримки — строки реакції на збої, порядок передачі правок і канал для термінових питань.
Кейс: прибрали просідання та прискорили випуск оновлень
Проєкт — казуальна головоломка: розробка гри на Flutter велася на Flame, рівні генерувалися процедурно й оновлювалися контентом щотижня.
До третьої великої гілки функціональності накопичилися три пов'язані проблеми: логіка та рендеринг йшли одним проходом ігрового циклу, під кожен рівень створювалися нові об'єкти замість перевикористання, а реліз перезбирався повністю навіть коли змінювалася лише розмітка рівнів.
Що переписали
Ігровий цикл розділили на фіксований крок логіки та окремий прохід рендерингу — відклик керування перестав залежати від плавності кадрів. Пул об'єктів замінив постійні алокації: збирач сміття більше не спрацьовував посеред рівня і не давав ривків.
Ресурси отримали профіль якості — на слабких пристроях вимикаються важкі ефекти й частина анімацій, але правила та відклик керування не змінюються.
Розмітку рівнів винесли в окремий пакет, тому правка контенту більше не потребує повного перезбирання: оновлення готується за години, а не за дні.
Метрики до і після
- Частка вильотів за сесію: знизилася з 7-8% до 1.5%
- Сесії з просіданнями та ривками: з 20% до 4%
- Повна збірка релізу: з 40 хвилин до 9
- Цикл випуску оновлення: з трьох тижнів до 5-7 днів
Окремо закріпили автоматичний збір звітів про падіння за пристроями й версіями — регресії тепер видно до релізу, а не за відгуками.
Чим спеціалізований рушій відрізняється від звичайного застосунку
Звичайний застосунок живе на подіях: екран побудований, чекає натискань і перемальовується тільки за зміни даних. Грі цього мало — потрібен безперервний цикл оновлення, де кожен тік перераховуються позиції, зіткнення та анімація, і лише потім збирається кадр. Пропущений тік гравець бачить як ривок.
Рендеринг ігрової сцени влаштований інакше: у кадрі одночасно живуть десятки об'єктів, спрайти збирають в атласи, а об'єкти беруть із пулу замість створення нових — інакше збирач сміття дає провали за часом кадру.
Застосунок оперує деревом віджетів і перебудовує тільки змінені вузли, гра — плоским списком шарів із жорстким порядком виведення.
| Ознака | Ігровий проєкт | Звичайний застосунок |
|---|---|---|
| Оновлення | Безперервний цикл кадрів | Тільки за зміни даних |
| Рендеринг | Сцена: шари та спрайти | Дерево віджетів і розмітка |
| Стан | Єдина модель світу | Розподілено за екранами |
| Ввід | Опитування кожен тік | Події жестів |
Архітектура розходиться ще сильніше: у застосунку стан розподілено за екранами та навігацією, а ввід надходить подіями від системи.
У грі є одна модель світу, до якої звертаються всі підсистеми, а ввід опитується кожен тік — так утримання кнопки та комбінації працюють передбачувано.
Рушій на кшталт Flame потрібен, коли картинка змінюється безперервно: фізика, зіткнення, багато об'єктів, рівний темп на слабких пристроях. Для форм, стрічок і списків він надлишковий — там достатньо звичайного застосунку на тій самій платформі, і підтримувати його простіше.
Часті технічні питання щодо архітектури проєкту
П'ять питань зазвичай спливають до старту розробки. Нижче — короткі відповіді: яке інженерне рішення стоїть за кожним і де проходить межа його застосовності.
Як тестується ігрова логіка, а не тільки інтерфейс?
Ігрове ядро відокремлюємо від шару рендерингу: правила, економіка, генерація рівнів і підрахунок очок живуть у незалежних модулях. Їх проганяють тестами на сценаріях — смерть персонажа, переповнення ресурсу, одночасні події. На пристрої залишається перевірка відклику та плавності.
Чи можна оновлювати гру без повторної публікації?
Контент, баланс і тексти виносимо в віддалені налаштування: правки доїжджають до гравців без збірки й модерації. Логіка та дозволи залишаються всередині застосунку — їх змінює тільки нова версія.
Що буде з кодом, коли автор піде з проєкту?
Архітектура розбита на модулі з явними контрактами, а рішення та залежності зафіксовані в документації. Новий інженер входить у проєкт за нею, а не за пам'яттю попереднього розробника.
Кому належить вихідний код?
Замовнику: сховище коду, конфігурації збірки та права на акаунти передаються за актом. Ми не утримуємо проєкт через доступи.
Що відбувається після релізу?
Стежимо за падіннями та утриманням, готуємо оновлення сумісності з новими версіями систем. Правки контенту йдуть без збірки, решта — за циклом релізів.
Обговоримо завдання: що потрібно для плану й оцінки
Щоб оцінка з розробки гри на Flutter спиралася на факти, а не на здогадки, нам потрібен короткий набір вхідних даних — вони напряму задають обсяг робіт і ризики. Нічого екзотичного, зазвичай це те, що вже сформульовано у вас у чернетках або в голові:
- мета гри та основний цикл: що гравець робить у перші хвилини і навіщо повертається;
- платформи й орієнтація: iOS, Android чи обидві, портретна чи ландшафтна, чи потрібні планшети;
- графіка та звук: чи є готові спрайти, анімації, музика або художню частину готуємо разом із вами;
- механіки: рівні, прогрес, збереження, внутрішньоігрова економіка, реклама та вбудовані покупки;
- дані: чи потрібен акаунт, хмарні збереження, таблиці лідерів, збір аналітики;
- обмеження: строки, прив'язки до домену, наявного сервера, магазинів застосунків;
- доступи: акаунти розробника в магазинах, якщо публікація на нашій стороні.
У відповідь повертаємо схему рішення: як розкладемо ігровий цикл за сценами, де пройдуть межі між логікою та рендерингом, як зберемо проєкт під обидві платформи і як випускати оновлення без перевипуску.
Поруч — склад робіт за етапами, строки та порядок передачі: вихідні коди, доступи, інструкція з релізу.
Опишіть завдання в зручному вигляді — повернемося з оцінкою та планом робіт з гри, після узгодження призначаємо старт проєкту.







