Проектування архітектури програмного кода ігор
Через рік розробки без архітектури відбувається таке: GameManager — клас на 3000 рядків, який знає про все. PlayerController чіпляється напрямки до UIManager, тому що «так швидше». Система квестів вызывает SaveSystem, який викликає EventSystem, який викликає QuestSystem — circular dependency, який неможливо розпутати без переписування половини гри. Новий розробник у команді боїться трогати код, тому що незрозуміло, що на що впливає.
Це не абстрактна теорія — це те, що ми бачимо в проектах, які приходять на оптимізацію або масштабування після 6–12 місяців активної розробки без архітектурного плану.
Паттерни, які працюють у розробці ігор
Service Locator vs Dependency Injection. У Unity класичний вибір. DI-фреймворки (Zenject/Extenject, VContainer) дають повноцінний IoC Container з constructor injection. Це правильно з SOLID точки зору, але вимагає дисципліни команди. Service Locator (через статичний реєстр сервісів) — компроміс: простіший у освоєнні, не вимагає розуміння DI-контейнерів, але втрачає переваги тестованості. Для малих команд (2–4 програмісти) часто вибираємо VContainer як баланс між суворістю та простотою.
Event-driven архітектура через ScriptableObject Events. Паттерн від Ryan Hipple (Unite 2017): ScriptableObject як канал подій. Компоненти підписуються на GameEvent-ассети, не знаючи один про одного. Player берен урон → викликає playerDamagedEvent.Raise(). HUD слухає цей івент та оновлює HP-бар. VFX-менеджер слухає та спавнить ефект. Ніяких прямих посилань. Це вирішує проблему зв'язаності та спрощує роботу у великій команді — художник може підключити свій ефект до ючення без правки коду.
ECS для високопродуктивного коду. Unity DOTS (Entities 1.x) виправданий там, де потрібно оновлювати тисячі об'єктів: симуляція частинок, RTS зі сотнями юнітів, процедурний світ. Вхід у DOTS вимагає повної переробки архітектури — це не «добавимо поверх». Рішення приймається на початку проекту.
State Machine як основа персонажної логіки. Hierarchical State Machine (HSM) для AI та Player Controller — не Animator State Machine (це тільки для анімацій), а окремого реалізація у коді. Для простих випадків — власна реалізація через enum та switch. Для складних (5+ станів з переходами) — бібліотека типу Stateless або Bolt (Ludiq). Явні стани усувають «спагетті» з boolean-флагів: isAttacking && !isStunned && canJump && !isReloading.
Структура проекту та розділення відповідальності
Ми проектуємо архітектуру, виходячи з двох ключових принципів: модулі не повинні знати про існування один одного, та бізнес-логіка не повинна залежати від Unity-специфічного коду.
Другий принцип дозволяє тестувати логіку через звичайні C# unit tests без запуску PlayMode. Якщо система розрахунку урону в RPG — це чистий C# клас без MonoBehaviour — її можна покрити тестами за годину. Якщо вона живе всередині PlayerController.Update() — тестування вимагає запуску сцени з персонажем.
Типова шаруваста архітектура для Unity-проекту:
- Domain — чисті C# класи: моделі даних, бізнес-логіка (DamageCalculator, QuestLogic, SaveData)
- Application — Use Cases, координація між доменними сервісами
- Infrastructure — Unity-специфічний код (MonoBehaviour, ScriptableObject, Addressables), мережеві виклики, збереження
- Presentation — UI, візуальні ефекти, аудіо
Реальний кейс: мобільна стратегія, команда 6 чоловік. Після 4 місяців розробки — 40% часу йшло на баґ-фіксинг побічних ефектів: зміна однієї системи ломала іншу. Провели архітектурний рефакторинг за 3 тижні: ввели VContainer для DI, виділили Domain-шар з GameManager, замінили прямі посилання між компонентами на ScriptableObject Events. Наступні 2 місяці — нуль регресійних баґів від рефакторингу.
Процес проектування архітектури
Починаємо з аналізу вимог: тип гри, команда, строки, майбутні фічі. Архітектура повинна відповідати масштабу — для гіпер-казуального з 3 системами та командою 2 чоловіка Zenject надлишковий.
Створюємо Architecture Decision Record (ADR) — документ з обґрунтуванням кожного ключового архітектурного рішення. Чому VContainer, а не Zenject. Чому ScriptableObject Events, а не UnityEvent. Чому Addressables, а не Resources. ADR стає частиною технічної документації проекту.
Готуємо структуру папок проекту, naming conventions, шаблонні класи для основних паттернів. Перші 2 тижні — парна розробка з командою для закріплення паттернів.
| Масштаб завдання | Орієнтовні строки |
|---|---|
| Консультація + архітектурний план (новий проект) | 3–7 днів |
| Рефакторинг архітектури існуючого проекту | 3–8 тижнів |
| Повне проектування архітектури з документацією | 2–4 тижні |
| Впровадження ECS/DOTS у проект | 4–10 тижнів |
Вартість розраховується індивідуально після аудиту проекту або концепції.





