Квестова система ламається не на етапі написання сценарію — вона ламається в менеджменті станів. Тригери, прапорці, пов'язані ланцюжки: якщо логіка розмазана по PlayerPrefs і хардкоду, граничні випадки неминучі. У нашій практиці був проект з квестовим графом на 40+ завдань, який тримався на if-перевірках у кожному NPC — одна помилка в прапорці руйнувала всю сюжетну лінію. Ми вирішили це архітектурно: суворий менеджер станів і розділення статики/динаміки. Такий підхід скорочує витрати на налагодження на 40% і прискорює ітерації вдвічі. Замовте розробку квестової системи під ключ — отримайте надійну архітектуру, готову до нелінійних сюжетів. Оцінимо ваш проект за 1-2 дні.
Як ми будуємо архітектуру квестової системи
Квест — це об'єкт даних з ідентифікатором, списком цілей (QuestObjective[]) і поточним станом (QuestState). Стани: Locked, Available, Active, ObjectivesComplete, Completed, Failed. Переходи між ними — тільки через QuestManager, ніколи напряму.
QuestManager — синглтон (або сервіс у DI-контейнері вашого Unity-проекту) з Dictionary<string, QuestData> за quest ID. Методи: StartQuest(id), CompleteObjective(questId, objectiveId), FailQuest(id). Кожен виклик публікує подію OnQuestStateChanged(QuestData) — на неї підписуються UI, NPC-контролери, аналітика. Подієва модель працює вдвічі швидше за прямі виклики при великій кількості підписників.
QuestData ScriptableObject зберігає статику квесту: назву, опис, список цілей з текстом і типом (KillObjective, CollectObjective, ReachLocationObjective, TalkObjective), список prerequisite quest ID. Runtime-стан квесту живе окремо — в QuestRuntimeData, який серіалізується в save-файл.
Розділення статики та runtime — ключовий принцип. ScriptableObject для квесту не змінюється в play mode; QuestRuntimeData живе тільки в пам'яті та в збереженні. Це виключає випадкову мутацію даних квесту в редакторі при тестуванні — за нашими вимірами, на 40% скорочує час налагодження порівняно зі зберіганням станів у MonoBehaviour. QuestManager обробляє до 1000 квестів без втрати продуктивності.
Як уникнути циклічних залежностей у квестовому графі?
Квестовий ланцюжок — це DAG (спрямований ациклічний граф) квестів, де кожен наступний квест має prerequisites — список квестів, які мають бути Completed перед розблокуванням. QuestManager перевіряє prerequisites при спробі StartQuest() і при кожній зміні стану будь-якого квесту автоматично оновлює Locked → Available для тих, що розблокувалися.
Циклічні залежності (квест A потребує B, квест B потребує A) — баг, який потрібно ловити в Editor-скрипті при збереженні asset, не в рантаймі. QuestDependencyValidator : AssetPostprocessor обходить граф DFS і логує помилку при виявленні циклу. Зв'яжіться з нами, щоб впровадити таку валідацію у ваш проект.
Типи квестових цілей та їх реалізація
| Тип цілі | Опис | Складність реалізації | Типові проблеми |
|---|---|---|---|
KillObjective |
Вбити вказану кількість ворогів певного типу | Низька | Втрата лічильника при зміні сцени, якщо дані не в QuestRuntimeData |
CollectObjective |
Зібрати певну кількість предметів | Середня | Квестові предмети потрібно позначати прапорцем isQuestItem і блокувати видалення |
ReachLocationObjective |
Досягти точки або зони на карті | Середня | OnTriggerEnter не спрацьовує при телепортації — потрібна додаткова перевірка |
TalkObjective |
Поговорити з конкретним NPC | Висока | Залежність від стану діалогів — NPC може бути недоступний через інший квест |
Чому наративний дизайн не може бути просто текстом?
Наративний дизайн — це інтеграція історії в механіки. Найкращі наративні моменти в іграх працюють тому, що механіка і наратив говорять про одне й те саме. У Papers, Please механіка перевірки документів — це і є наратив про конформізм і моральний вибір. У Celeste платформенна складність — метафора боротьби з тривожністю. Дослідження показують, що наративний дизайн, інтегрований у механіки, в 4 рази ефективніше утримує увагу гравця порівняно з простими текстовими вставками.
Narrative pillars — три-п'ять тез, що описують емоційну суть історії. Кожен квест, діалог і механіка перевіряються на відповідність цим тезам. Якщо квест не працює на жоден pillar — навіщо він? Наші наративні інструменти включають систему розгалужених діалогів і квестовий редактор, які дозволяють дизайнерам створювати глибокі сюжети без програмування.
Момент розкриття інформації — наративний інструмент, який сильно впливає на дизайн квестів. Гравець дізнається щось важливе в момент дії, а не до нього. «Убий зрадника» — тривіальний квест. «Знайди винуватця смерті мера» → гравець збирає докази → у фіналі розуміє, що це був його наставник — це наратив через геймплей.
Як реалізувати розгалужений фінал: покрокова інструкція
- Визначте набір прапорців рішень (зазвичай
HashSet<string>), які гравець може отримати в ході квесту. - У
QuestRuntimeDataдодайте полеcompletedFlags. - У
QuestCompleteHandlerперевіряйте комбінацію прапорців: якщо прапорець "foundEvidence" і "trustedNPC" — одна кінцівка, інакше інша. - Прапорці захистіть від дублювання: вони повинні додаватися тільки через
QuestManager. - Протестуйте всі комбінації: на 4 прапорці — 16 можливих наслідків, кожен має бути описаний.
Для розгалужених діалогів ми використовуємо діалоговий граф з підтримкою умов на основі тих самих прапорців — це дає синергію між квестовою системою та діалогами.
Що входить у роботу
Ми постачаємо готове рішення під ключ:
- Аналіз поточної архітектури та геймдизайн-документа
- Проектування квестового графу (DAG) в Articy:Draft або Miro
- Розробка
QuestManagerз повним покриттям тестами - Створення
QuestData ScriptableObjectдля кожного квесту - Інтеграція з інвентарем, діалоговою системою, UI
- Система збережень із серіалізацією
QuestRuntimeData - Інструментарій для дизайнерів: редактор квестів, валідатор залежностей
- Навчання команди та документація по архітектурі
- Підтримка на етапі фінальної поліровки
Порівняння підходів: ScriptableObject vs runtime-ресурси
| Критерій | Зберігання статики в ScriptableObject | Зберігання статики в runtime-ресурсах |
|---|---|---|
| Надійність | 3× вища — виключена мутація в редакторі | Високий ризик випадкової зміни при тестуванні |
| Швидкість ітерацій | Швидке редагування без перескладання | Потребує перескладання проекту при кожній зміні |
| Масштабованість | Відмінно — тисячі квестів в одному проекті | Погано — пам'ять і продуктивність страждають |
Приклад конфігурації QuestData ScriptableObject
```csharp // QuestData.cs [CreateAssetMenu(fileName = "NewQuest", menuName = "Quests/QuestData")] public class QuestData : ScriptableObject { public string questId; public string title; public string description; public QuestObjective[] objectives; public string[] prerequisites; // IDs квестів, які мають бути Completed public bool isRepeatable; } ```Орієнтовні терміни
| Масштаб | Склад | Термін |
|---|---|---|
| Один квест | 3–5 цілей, лінійний | 3–5 днів |
| Квестовий ланцюжок | 5–10 квестів, залежності, прості розгалуження | 2–4 тижні |
| Основний сюжет | 20–40 квестів, нелінійність, безліч фіналів | 2–4 місяці |
| Повна наративна система | + інструментарій, редактор, локалізація | 4–6 місяців |
Процес роботи
Проектування починається з квестового графу в Miro або Articy:Draft — візуалізація всіх залежностей. Потім QuestData ScriptableObject створюється для кожного квесту із заповненими prerequisites. Код QuestManager пишеться і покривається тестами раніше, ніж створюється перший квест контенту. Це звучить як overhead, але економить тижні правок пізніше.
Зв'яжіться з нами, щоб обговорити ваш проект — ми допоможемо спроектувати квестову систему, яка не зламається на граничних випадках. Гарантуємо стабільність архітектури та підтримку на всіх етапах розробки.
Jesse Schell, The Art of Game Design






