Власний Game Engine: як і навіщо створювати ігровий рушій

Розробник Тайлер Глейел (Tyler Glaiel) розповів у своєму блозі, як створювати власний ігровий рушій, якщо ви шукаєте альтернативу комерційним Unity чи Unreal. Переказуємо його поради.

Навіщо це взагалі потрібно

Хороших причин є декілька:

  • Нова технологія: скажімо, ви плануєте створити гру з новою технологією, яка в інших рушіях поки не підтримується або цю підтримку реалізувати складно.
  • Спеціалізація: ви хочете оптимізувати розробку саме своїх ігор. Вам не потрібні всі функції, які є в комерційних рушіях, тому можна підлаштувати під себе конвеєр ресурсів, редактор рівнів абощо — щоб вони виконували лише потрібні вам задачі.
  • Незалежність: ви не хочете мати справу з чиєюсь іншою технологією у перспективі. Цінності компаній на кшталт Unity чи Epic не завжди збігатимуться з вашими й ви хочете контролювати процес самостійно.
  • Цікавість: зрештою, створити власний рушій — найкращий спосіб розібратись, як все працює.

Можуть бути й погані причини. Якщо одна з них — це єдине, що спонукає вас створити рушій, радимо подумати двічі. Серед таких причин:

  • Я можу зробити все краще: загалом ви навряд зробите щось в усіх напрямках краще за Unity, Unreal, Godot чи GameMaker. Можна поліпшити рушій для конкретного призначення, але не для універсального застосування. Особливо, якщо ви робите це вперше.
  • Це те, що роблять справжні програмісти: немає єдиного правильного Шляху Розробника. Якщо ваша гра добре працює на готових рушіях (а зазвичай так і є), то не соромно їх застосовувати. Зрештою, рушій — це просто інструмент.
  • Економія грошей або часу: навряд чи вам вдасться заощадити. Створення рушія — це час, а час — це гроші. На той самий Unity ви витратите менше ресурсів, ніж на власну технологію.

До того ж ви маєте оцінити власний досвід та поставлені цілі. Якщо ви створили не дуже багато ігор, то рушій розробити буде складніше (а без досвіду з іграми це взагалі неможливо). До того ж з 3D працювати буде важче, ніж просто з 2D.

Загалом є чимало причин створити свій рушій: приємно, мати власну технологію, яку можна полагодити власноруч, а не чекати голосу згори, коли щось піде не так. Водночас і гасити пожежі теж доведеться власноруч. Повний контроль і повна відповідальність.

Що таке рушій

Для початку визначимось з термінологією. Ігровий рушій — це каркас, на який лягає ваша гра. З ним ви можете дбати про ігрову логіку і не думати про те, як надіслати трикутник на відеокарту.

Насправді є різниця між рушіями й тим, скільки роботи вони за вас виконують. Деякі просто відображають графіку (Flash, Pico-8), а деякі глибоко спеціалізуються на конкретних жанрах гри й одразу містять чимало ігрової логіки (RPGMaker, Ren’Py).

Ігрові рушії зазвичай створюються поверх низькорівневих фреймворків (на кшталт SDL чи OpenGL) та містять бібліотеки для роботи звуку, фізики, математики тощо. Якщо ви робите власний рушій, то не маєте писати кожен шматочок окремо, можна цілком взяти щось корисне й готове, як от SDL. Також треба зібрати потрібний набір бібліотек для ваших задач.

Поговоримо про базовий набір можливостей, який має бути у вашому рушії. Необхідний мінімум:

  • Ініціалізація системи: запуск вікон, отримання контексту OpenGL / DirectX / Vulkan, ініціалізація аудіо. Це вміє робити SDL, тож просто скористайтесь ним, не треба вигадувати велосипед.
  • Контроль синхронізації кадрів: якщо ваша грає має працювати зі швидкістю 60 кадрів в секунду, потрібен якийсь таймер і цикл, які контролюватимуть час оновлення та візуалізації.
  • Введення: є багато способів реагувати на натискання кнопки: можна просто запитувати поточний стан кнопки або реєструвати події, це не має значення. SDL подбає про взаємодію з кнопками: якщо ви застосовуєте його для ініціалізації системи, то й тут він вам знадобиться. Ви можете створити дійсно потужну та гнучку інпут-систему, але спочатку не потрібно робити нічого, крім основних функцій.
  • Рендеринг: більшість ігор хоч якось використовують графіку — і за це має відповідати ваш рушій. Якщо ви робите 2D-гру, щонайменше треба відображати текстуровані прямокутники. Шейдери, VBO, render target, меші, матеріали — все це чудово, але про це можна подбати пізніше. Можна поколупатись в OpenGL чи Vulkan і зробити рендерер власноруч, але знову ж таки — немає нічого поганого у готових бібліотеках типу Ogre3D.
  • Математика та утиліти: «вектори й матрична математика», може, і не є повноцінною системою, але краще мати таку допоміжну бібліотеку, до якої отримують доступ рушій і ігровий код. Плюс будь-які інші випадкові корисні функції та формули, які вам трапляються під час розробки. Для цього ж можна скористатися бібліотеками STB.

Ще є кілька систем, які важливі й потрібні, але додати їх можна не одразу, а тоді, коли вони справді вам знадобляться.

  • Управління ігровими об’єктами й сценою: кодувати все зразу в одну велику функцію оновлення — не так погано, як здається. Та якщо ваша гра стає хоч трохи складною, знадобиться якась система для обробки окремих ігрових об’єктів та колекцій. Це дуже важлива частина вашого рушія, адже вона визначає, якою буде логіка гри. Будуть ваші об’єкти деревами з системою успадкування? Чи складаються вони з менших компонентів? Чи застосовується ECS? (До речі, не варто брати «чистий» ECS, якщо у вас немає конкретного варіанту використання.) На які типи подій вони реагують? Як відбувається запит на взаємодію з іншими об’єктами? Як щодо використання пам’яті? За все це відповідає система управління ігровими об’єктами й сценою. Для неї є кілька бібліотек, особливо для чистого ECS. Та оскільки ця система впливає на вигляд буквально всього коду гри, то є сенс зробити все власноруч. Готові рішення означають, що доведеться пристосовуватись, а ми ж хочемо цього уникнути.
  • Звук: звукові ефекти та музика — буцім як окремі системи, та обидві стосуються аудіовідтворення. Основне, що вам потрібно, це можливість почати й зупинити музику та відтворювати одноразові звукові ефекти. Це, звісно, не все, але для початку вистачить. Мінус в тому, що стандартні аудіофреймворки (FMod і Wwise) — комерційні та мають купу ліцензійних обмежень. Є ще чимало відкритих фреймворків, та вони незручні й люто дратують (привіт, OpenAL). Простим і чудовим рішенням здається FAudio, на базі якого можна створювати й складніші речі зі звуком.
  • Завантаження і керування файлами: у всі ігри потрібно завантажувати файли, тож треба знайти спосіб, аби це робити. Навряд чи ви хочете сильно їх декодувати вже завантажені файли, тож для цього має бути який базовий обробник. Скажімо, ви хочете створити підтримку модів або динамічне завантаження/вивантаження тощо. Коли у вас є база і ви завантажуєте файли лише через файловий менеджер, то потім можна легко додати будь-які інші функції.
  • Мережа: гаразд, мережа (онлайн мультиплеєр) це ЗОВСІМ не обов’язкова можливість (якщо вам не потрібен багатокористувацький режим, то взагалі не думайте про цей пункт). Однак цю систему вкрай складно причепити до вже готового рушія, тому краще подбати про неї заздалегідь, якщо вона все ж потрібна.

Це базовий набір систем, які вам потрібні для створення рушія. Все інше — виявлення зіткнень, фізика, серіалізація, анімація, UI — залишається на ваш розсуд. У більшості рушіїв усе це є, бо це поширені й потрібні речі, але гру можна створити й без них.

Можна обмежитись простими перевірками зіткнень у своїй бібліотеці математичних утиліт, а тоді просто дозволити ігровій логіці робити все вручну. Базову гравітацію та прискорення теж можна робити без фізичного рушія типу Box2D або Bullet. А повна серіалізація взагалі може бути зайвою якщо вам треба лише зберегти чекпоінт.

Дуже гарна ідея — ознайомитися з тим, як працюють інші ігрові рушії, перш ніж починати створювати власний. Дізнайтеся, які парадигми та структури вони використовують, що в них тішить, а що дратує. Створіть невелику гру з купою різних рушіїв, якщо можете, просто щоб отримати ці знання.

Як створювати рушій

Перше і єдине непорушне правило — створюйте гру одночасно з рушієм. Вивчіть основи та одразу починайте створювати гру, рушій без гри — ніщо.

Це важливо, тому що особливості рушія будуть залежати від потреб гри. Ви не дізнаєтесь, де саме проблеми з швидкодією, якщо у вас немає гри. Вам треба якась деревоподібна структура для вашого світу, щоб не оновлювати й не рендерити об’єкти, які далеко від камери? А хтозна. Ніхто не знає, доки ми не запуститимо масштабний рівень гри, що буде працювати як трясця. Та й тоді оновлення об’єктів може бути проблемою і ви про це знатимете, доки не спрофілюєте його.

Не пишіть код, який вам зараз не потрібен. Якщо єдиний UI у вашій грі — це кнопка play в головному меню, то вітання! Вам не треба будувати химерну UI-систему для рушія. Гра End Is Nigh йде без фізичного рушія і навіть без широкофазного зіткнення. Та навіть без системи камери, бо вона там просто не потрібна. Ще можна використати замість складнющого редактора звичайну електронну таблицю .csv, щоб упорядкувати карту світу, це легко і цілком працює (перевірено).

Є безліч способів реалізації цих систем, не існує найкращих універсальних шляхів, все залежить від вашої гри. Почніть з основного та додавайте можливості поступово, коли вони треба.

Щодо мов програмування: використовуйте те, що вам зручно. Створення рушія й без того складне, а вчити ще й C++ по дорозі — означає помножити складність вдвічі. Мова C# ідеальна для рушіїв. Повільніша за C++, а не настільки, щоб це було важливо. Щось дійсно повільне на кшталт Python може бути проблемою, якщо ви маєте багато рухомих частинок, але для деяких ігор все одно згодиться. Головне, щоб було зручно.

Ще одне — все не буде працювати правильно з першої спроби. Ніколи. Треба просто змиритись і вчитись на своєму досвіді: вчитись, робити гру — і так по колу, доки рушій не працюватиме добре.


Тут немає жодних технічних деталей про те, як реалізувати всі ці системи, адже це сильно залежить від випадку використання. Цілком прийнятних способів є сотні. Головне — це з’ясувати, що працюватиме саме для вас.

Підписуйтеся на Telegram-канал @gamedev_dou, щоб не пропустити найважливіші статті і новини.

👍НравитсяПонравилось4
В избранноеВ избранном0
LinkedIn
Допустимые теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Допустимые теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

Подписаться на комментарии