Розробка систем досягнень (Achievements) та лідербордів
Досягнення та лідерборди — не декоративні елементи. Правильно вистроєна система achievement утримує гравця через цілі другого плану, а лідерборд створює соціальний тиск, який працює краще більшості push-уведомлень. Але технічно обидві системи мають неочевидні грабіжки, на яких ломаються навіть досвідчені команди.
Чому досягнення складніше, ніж кажутся
На старті проекту досягнення виглядають просто: флаг в базі, перевірка умови, запис. На практиці через півроку розробки виявляється:
Стан лічильників рассинхронізований. Досягнення «вбий 100 гоблінів» потребує персистентного лічильника, що оновлюється при кожному вбивстві. Якщо гравець переустановив гру, лічильник скинувся — досягнення вже не отримати, хоча в Google Play / Game Center позначено як виконане. Класична проблема dual-state: локальний стан та стан платформи розходяться.
Ретроактивні досягнення. Команда додає нове досягнення через три місяці після запуску. Гравці, які вже виконали умову, не отримують його автоматично. Потрібна процедура бекфілу — пересчёт по історичній статистиці гравця. Якщо статистика не зберігалась — бекфіл неможливий, гравці злі.
Thread-safety лічильників. У багатопоточному середовищі (Unity з Jobs System, серверна логіка) одночасне інкрементування лічильника без атомарних операцій дає неверні значення. Кілька івентів одночасно — лічильник прикпає через значення.
Архітектура системи досягнень
Робоча схема — event-driven архітектура через центральний AchievementService. Замість того щоб кожен ігровой модуль знав про досягнення та викликав AchievementManager.CheckCondition(), модулі кидають события: GameEvent.EnemyKilled(enemyType, count), GameEvent.LevelCompleted(levelId, stars). AchievementService підписаний на потрібні события та сам оновлює лічильники.
Кожне досягнення описується конфігом:
- тип (
incremental,single,compound) - список івентів, на які реагує
- умова завершення (лямбда або ScriptableObject з логікою)
- награда
Додання нового досягнення — новий конфіг, без змін в ігровому коді.
Синхронізація з платформами. Google Play Games Services та Apple Game Center мають власні лідерборди та досягнення, але працювати з ними прямо — біль. GPG SDK для Unity працює тільки на Android, Game Center — тільки на iOS. Для крос-платформенних проектів використовуємо проміжний шар: власна база зберігає master-стан, платформенні SDK оновлюються як супутники. При конфлікті (офлайн-сесія) — мерж по принципу «беремо максимум» для інкрементальних лічильників.
PlayFab та GameSparks надають готові серверні системи досягнень з API — для мобільних F2P це часто швидше та дешевше власного бекенда.
Лідерборди: складність в масштабі
Для гри з 1000 одночасних гравців SQLite або Postgres з ORDER BY score DESC LIMIT 100 працюють нормально. При 100k+ записів запит без правильних індексів починає тормозити. При 1M+ потрібен Redis Sorted Set.
Redis ZADD leaderboard {score} {userId} + ZREVRANK leaderboard {userId} дає O(log N) вставку та O(log N) отримання рейтингу. ZREVRANGE leaderboard 0 99 WITHSCORES — топ-100 за мікросекунди. Стандарт для мобільних ігор з великою аудиторією.
Анти-чіт для лідерборда. Клієнтська відправка score без валідації — пряма дорога до читерів на першому місці. Мінімум: score підписується HMAC-ключем на клієнті, сервер верифікує підпис. Нормально: сервер сам розраховує score по логам ігрової сесії, клієнт тільки відправляє события.
Тижневі та сезонні лідерборди. Окремена таблиця (або окремий Redis Sorted Set) на період + cron-джоб для ротації. При ротації — снапшот переможців в архів, розподіл наград через чергу (не синхронно — при великій аудиторії синхронна розподіл наград убиває сервер).
Етапи розробки
- Проектування схеми — типи досягнень, события, зберігання стану, платформи
- Серверна частина — таблиці/Redis, API endpoints, anti-cheat
- Клієнтська інтеграція — AchievementService, підписки на события, UI
- Платформенна синхронізація — GPG / Game Center / PlayFab
- Інструменти для геймдизайнера — редактор конфігів досягнень
- QA — тест ретроактивних досягнень, тест офлайн-сценаріїв, нагрузкові тест лідерборда
| Масштаб | Термін |
|---|---|
| Локальні досягнення без сервера (мобайл/casual) | 1–2 тижні |
| Серверні досягнення + лідерборди для однієї платформи | 3–5 тижнів |
| Крос-платформенна система з анти-читом та сезонними лідербордами | 6–12 тижнів |
Вартість визначається індивідуально після аналізу архітектури проекту та вимог до масштабованості.





