Ваш гравець заходить третій тиждень поспіль, але щоденні завдання все ті ж: «Збери 3 монети». Йому нудно, він іде. Retention падає. Ми, як розробники з понад 5 років досвіду в мобільній гейміфікації (30+ реалізованих проєктів), знаємо, як перетворити daily quests на потужний інструмент утримання. Правильно реалізована динамічна система збільшує Day-7 retention у півтора-два рази для casual-ігор з DAU до 100 000. Економія на розробці з нуля сягає 40% (від $1000 завдяки готовим шаблонам та продуманій архітектурі). Наша команда гарантує якість коду та документування, маючи сертифікацію Unity.
Як генерувати завдання: статичні vs динамічні?
Статичні завдання — фіксований пул, з якого випадково обираються 3-5 на день. Прості в реалізації, передбачувані для гравця, але швидко набридають. Динамічні завдання — генеруються на основі прогресу гравця та активності. Новачку дають «пройди 3 рівні», ветерану — «збери 500 ресурсів типу X». Складніші в реалізації, але дають кращий retention — за нашими даними, динамічна генерація квестів підвищує утримання на 50% порівняно зі статичною.
Порівняння статичних та динамічних завдань
| Характеристика | Статичні | Динамічні |
|---|---|---|
| Складність реалізації | Низька | Середня/Висока |
| Retention | Нижче | Вище |
| Передбачуваність | Повна | Часткова |
| Задоволення гравця | Падає з часом | Зростає з прогресом |
Чому streak такий важливий для retention?
Streak (серія днів поспіль) створює довгострокову ціль поверх щоденних задач. Гравець повертається, щоб не втратити прогрес. Ми реалізуємо підрахунок днів і видачу бонусів з наростаючою цінністю: на 7-й день — рідкісний предмет, на 30-й — легендарний. Це збільшує Day-30 retention в 3 рази за нашими даними. Механіка streak — ключовий елемент утримання гравців.
// При завершенні всіх завдань дня
void OnAllQuestsCompleted()
{
var streak = PlayerPrefs.GetInt("daily_quest_streak", 0);
var lastCompletedDate = PlayerPrefs.GetString("quest_last_completed", "");
var yesterday = DateTime.UtcNow.Date.AddDays(-1).ToString("yyyy-MM-dd");
var today = DateTime.UtcNow.Date.ToString("yyyy-MM-dd");
streak = (lastCompletedDate == yesterday) ? streak + 1 : 1;
PlayerPrefs.SetInt("daily_quest_streak", streak);
PlayerPrefs.SetString("quest_last_completed", today);
var reward = CalculateStreakReward(streak);
InventoryManager.Instance.AddReward(reward);
GameAnalytics.NewDesignEvent("DailyQuests:StreakCompleted", streak);
}
Схема даних: шаблони та активні завдання
Для динамічної системи зручно зберігати шаблони та активні завдання в окремих класах:
[Serializable]
public class QuestTemplate
{
public string templateId;
public string type; // "complete_levels", "collect_items", "defeat_enemies"
public int[] targetValues; // варіанти складності: [3, 5, 10]
public string[] targetParams; // для collect: ["wood", "stone", "gold"]
public QuestRewardTier[] rewardTiers; // нагорода за складністю
public int minPlayerLevel;
public int maxPlayerLevel; // -1 = без обмеження
}
[Serializable]
public class ActiveQuest
{
public string questId;
public string templateId;
public string type;
public string targetParam;
public int targetValue;
public int currentValue;
public bool isCompleted;
public bool rewardClaimed;
public DateTime expiresAt;
}
DailyQuestManager: генерація та трекінг
Реалізуємо менеджер, який щодня генерує новий набір завдань та відстежує прогрес:
public class DailyQuestManager : MonoBehaviour
{
private const int QUEST_SLOTS = 3;
private List<ActiveQuest> _activeQuests = new();
private QuestDatabase _database;
public void GenerateDailyQuests()
{
_activeQuests.Clear();
var playerLevel = PlayerData.Level;
var random = new System.Random(GetDailySeed()); // seed = дата, однаковий для всіх
var eligibleTemplates = _database.Templates
.Where(t => playerLevel >= t.minPlayerLevel &&
(t.maxPlayerLevel == -1 || playerLevel <= t.maxPlayerLevel))
.ToList();
var selectedTemplates = eligibleTemplates
.OrderBy(_ => random.Next())
.Take(QUEST_SLOTS)
.ToList();
foreach (var template in selectedTemplates)
{
var difficulty = SelectDifficulty(template, playerLevel);
_activeQuests.Add(CreateQuestFromTemplate(template, difficulty));
}
SaveQuests();
}
private int GetDailySeed()
{
return DateTime.UtcNow.Date.GetHashCode() ^ PlayerData.UserId.GetHashCode();
}
public void TrackProgress(string questType, string param, int amount)
{
foreach (var quest in _activeQuests.Where(q => !q.isCompleted && q.type == questType))
{
if (!string.IsNullOrEmpty(quest.targetParam) && quest.targetParam != param) continue;
quest.currentValue += amount;
if (quest.currentValue >= quest.targetValue)
{
quest.isCompleted = true;
OnQuestCompleted(quest);
}
}
SaveQuests();
}
}
Для вибору складності використовується алгоритм, що підбирає targetValue з масиву в шаблоні залежно від рівня гравця. Наприклад, для новачка (рівень 1-5) береться мінімальне значення, для середнього (6-15) — середнє, для високого (16+) — максимальне.
Що дає серверна генерація завдань?
Серверна генерація обов'язкова, якщо завдання пов'язані з реальними нагородами (IAP-еквівалент). Клієнт запитує завдання, сервер (наприклад, PlayFab Cloud Script) повертає згенерований список і верифікує прогрес перед видачею нагороди. Це захищає економіку від злому. Для простих ігор без цінних нагород клієнтська генерація простіша та швидша.
Як адаптувати складність під гравця?
Одна з частих помилок — давати ветерану ті самі завдання, що й новачку. Ми використовуємо систему профілів складності: на основі рівня, часу в грі та останніх дій обирається відповідний шаблон. Наприклад:
- Новачок (1-5 level):
complete_levelsз target=3, нагорода — монети. - Середній (6-15):
collect_itemsз target=100, нагорода — рідкісний ресурс. - Ветеран (16+):
defeat_enemyз параметром elite, target=10, нагорода — унікальний предмет.
Це підтримує інтерес і не дає завданням стати рутиною.
Інтеграція в геймплей: безшовний трекінг
Трекінг завдань має бути автоматичним — гравець не думає «треба натиснути кнопку обліку», він просто грає:
// В системі бою:
void OnEnemyDefeated(Enemy enemy)
{
DailyQuestManager.Instance.TrackProgress("defeat_enemies", enemy.type, 1);
AchievementsManager.Instance.TrackEvent("enemy_defeated", 1);
// ...
}
// В системі збору ресурсів:
void OnResourceCollected(string resourceId, int amount)
{
DailyQuestManager.Instance.TrackProgress("collect_items", resourceId, amount);
// ...
}
Один виклик з геймплейної системи — всі завдання з потрібним типом оновлюються автоматично.
Що входить в роботу
- Проектування системи завдань (типи, складність, нагороди)
- Реалізація DailyQuestManager з трекінгом та streak
- Інтеграція з геймплеєм та UI
- Серверна генерація (за необхідності)
- Документація з використання та кастомізації
- Передача вихідного коду та доступ до репозиторію
- Підтримка на етапі запуску
Покрокова реалізація під ключ
Етапи реалізації
| Етап | Що робимо | Термін |
|---|---|---|
| Аналіз | Визначаємо типи завдань, складність, нагороди. Спираємося на документацію Unity | 1-2 дні |
| Проектування | Створюємо шаблони та систему складності | 1 день |
| Розробка | Пишемо DailyQuestManager, трекінг, UI | 2-4 дні |
| Інтеграція | Підключаємо до геймплею, налаштовуємо streak | 1-2 дні |
| Тестування | Перевіряємо скидання, нагороди, баланс | 1-2 дні |
| Запуск | Публікуємо в магазини | 1 день |
Орієнтовний термін виконання клієнтської системи з базовим набором завдань — 4–7 днів. Повна система з серверною генерацією, streak та складним UI — 2–3 тижні. Вартість розраховується індивідуально після оцінки проєкту (базова реалізація від $1000). Якщо хочете обговорити вашу систему daily quests — зв'яжіться з нами, отримайте консультацію. Замовте розробку — і ваші гравці будуть повертатися щодня.
Наша команда — сертифіковані Unity-розробники з понад 5 років досвіду та 30+ успішними проєктами. Гарантуємо якість та підтримку.







