Реалізація Gacha/Lootbox механіки мобільної гри з pity-системою
Уявіть: у вас майже готова RPG, залишилося впровадити гачу, але юзер-тест показав, що гравці кидають після 50 ролів без легендарки — комбінація без pity-системи вбиває утримання. Або гірше: ви випустили оновлення, а через день у App Store приходить відмова — ймовірності не показані. Такі проблеми коштують грошей: переробка та повторна модерація можуть затягнутися на тижні, а тим часом конкуренти забирають вашу аудиторію. Ми допомагаємо цього уникнути: за 3–4 дні ставимо базову gacha із захистом від невдач, за 7–10 — повноцінну систему з банерами, анімаціями та звітами для маркету. Наш досвід — понад 40 проєктів, і кожен проходив рев'ю з першого разу. Не ризикуйте релізом — зв'яжіться з нами для аудиту вашої поточної механіки.
Математична модель ймовірностей
Базова gacha — зважений випадковий вибір з пулу нагород. Проста реалізація:
data class GachaItem(val id: String, val rarity: Rarity, val weight: Int)
fun rollGacha(pool: List<GachaItem>): GachaItem {
val totalWeight = pool.sumOf { it.weight }
var random = Random.nextInt(totalWeight)
for (item in pool) {
random -= item.weight
if (random < 0) return item
}
return pool.last()
}
Приклад розподілу ваг:
- Common: weight 1000 → ~58.8% шанс
- Rare: weight 500 → ~29.4%
- Epic: weight 150 → ~8.8%
- Legendary: weight 50 → ~2.9%
Сумарна вага: 1700. Шанс legendary: 50/1700 ≈ 2.94%.
Як працює pity-система?
Pity (гарантована нагорода) — механіка, яка гарантує legendary після N невдалих спроб. Без pity у гравця може бути streak з 200 ролів без legendary — математично можливо, практично руйнує досвід.
Soft pity — починаючи з N-го ролу ймовірність legendary зростає. Genshin Impact використовує цей підхід: з 74-го ролу шанс 5* починає зростати на 6% кожен рол.
Hard pity — рівно на N-му ролі legendary гарантований. Простіше реалізувати та чесніше комунікувати гравцю.
data class PlayerGachaPity(
val rollsSinceLastLegendary: Int,
val softPityStart: Int = 74,
val hardPityAt: Int = 90
)
fun calculateEffectiveProbability(baseProbability: Float, pity: PlayerGachaPity): Float {
if (pity.rollsSinceLastLegendary >= pity.hardPityAt) return 1.0f
if (pity.rollsSinceLastLegendary >= pity.softPityStart) {
val excess = pity.rollsSinceLastLegendary - pity.softPityStart
return minOf(1.0f, baseProbability + excess * 0.06f)
}
return baseProbability
}
Pity-лічильник зберігається на сервері, не на клієнті. Клієнтський лічильник обнуляється при перевстановленні — гравець втрачає накопичений pity, що викликає справедливе обурення та чарджбеки.
Навіщо серверна генерація?
Результат гача-ролу не можна генерувати на клієнті. Серверна генерація в 100 разів надійніша за клієнтську — зламати її майже неможливо. Схема:
- Клієнт надсилає запит
POST /gacha/roll з userId, gachaPoolId, кількістю ролів, токеном оплати
- Сервер перевіряє баланс/транзакцію, дістає pity-лічильник, генерує результат з seeded PRNG
- Сервер записує результат, оновлює pity, повертає
rollId + результати
- Клієнт відображає анімацію та показує результати
Seed для PRNG генерується на сервері, клієнт не може передбачити або вплинути на результат.
Анімація відкриття
Анімація gacha-ролу — не просто прикраса, це психологічно значущий момент. Тривалість 2–4 секунди, наростаючий саспенс перед reveal. Для мобільної реалізації використовуємо:
- Unity Animator або Spine для 2D-анімацій карт/яєць
- Particle System для ефектів при reveal рідкісних нагород
- Haptic feedback (UIImpactFeedbackGenerator на iOS, VibrationEffect на Android) в момент reveal
Multi-pull анімації (x10 рол) потребують окремої логіки: показуємо всі результати послідовно зі зростаючим темпом, common швидко, legendary — з повноекранним ефектом.
Регуляторні вимоги
App Store вимагає відображення ймовірностей «перед покупкою». Google Play — аналогічна вимога. Реалізація: екран «Деталі гача-пулу» з таблицею ймовірностей за типами нагород. Цей екран відкривається кнопкою «i» (інформація) поруч з кнопкою ролу.
| Рідкість |
Ймовірність |
Гарантія (hard pity) |
| Common |
58.8% |
— |
| Rare |
29.4% |
— |
| Epic |
8.8% |
40 ролів |
| Legendary |
2.9% |
90 ролів |
Які типи gacha-банерів існують?
| Тип банеру |
Тривалість |
Rate-up |
Pity сумісність |
Дохідність |
| Standard |
Постійно |
Ні |
Так |
Стабільна |
| Rate-up |
7–14 днів |
Так |
Так (з гарантом) |
Висока |
| Featured |
7–14 днів |
Так |
50/50 guarantee |
Максимальна |
Rate-up banner — тимчасовий пул з підвищеним шансом конкретного персонажа/предмета. Створює urgency та піки доходу. Standard banner — постійний пул, приймає «втрачені» pity-перемоги в системах з гарантом. Featured banner з guarantee — якщо rate-up не випав на 1-му legendary, наступний guaranteed буде featured (система «50/50»).
Чек-лист: що входить в роботу
- Аналіз вимог та проектування математичної моделі
- Реалізація серверної та клієнтської логіки (Swift/Kotlin/Flutter)
- Інтеграція pity-системи та rate-up банерів
- Верстка UI з відображенням ймовірностей
- Створення анімацій відкриття (2D/3D)
- Тестування на навантаження (500+ одночасних ролів)
- Підготовка документів для публікації в App Store та Google Play
- Пост-релізна підтримка: моніторинг, доопрацювання за метриками
Терміни орієнтовно
Базова gacha з pity та серверною генерацією — 3–4 дні. Повна система з кількома типами банерів, UI ймовірностей, анімаціями та аналітикою — 7–10 днів. Вартість розраховується індивідуально — напишіть нам для оцінки.
Отримайте консультацію — ми допоможемо спроектувати gacha-систему, яка принесе прибуток та пройде модерацію.
Монетизація мобільних додатків: IAP, підписки та рекламна медіація
Додаток з погано реалізованими покупками втрачає гроші не тому що користувачі не хочуть платити, а тому що StoreKit транзакція зависає, Receipt Validation падає з помилкою або restore purchases не працює — і користувач пише в підтримку або залишає 1 зірку. Наш досвід (більше 7 років у мобільній розробці) показує, що грамотна монетизація збільшує LTV на 30–60% вже в перші три місяці після впровадження. Отримайте консультацію з монетизації вашого додатка — проаналізуємо поточну модель і знайдемо точки зростання.
Чому StoreKit 2 — найкращий вибір для IAP?
StoreKit 2 (iOS 15+) — сучасний API з async/await та верифікованими транзакціями на стороні пристрою без сервера. Transaction.currentEntitlements повертає всі активні покупки. Ключова зміна порівняно з StoreKit 1: верифікація JWS-підпису на пристрої через VerificationResult<Transaction> — не потрібно надсилати receipt на сервер для базової перевірки.
Але сервер-сайд валідація все одно потрібна для consumable покупок та проти fraud. App Store Server API замінює старий /verifyReceipt endpoint. Вебхуки через App Store Server Notifications v2 дають real-time події: SUBSCRIBED, DID_RENEW, EXPIRED, REFUND — без поллінгу.
Типова помилка: не обробляють paymentQueue(_:updatedTransactions:) у фоні для незавершених транзакцій. Користувач купив consumable, додаток впав до finishTransaction — покупка висить у черзі, при наступному запуску відновлюється та вимагає повторної обробки на сервері. Без ідемпотентності сервера — подвійне нарахування.
Як не втратити дохід на підписках?
Підписочна модель вимагає відстеження станів: тріал → активна → grace period → expired → refunded. RevenueCat — фактичний стандарт для керування підписками в продакшні. Абстрагує StoreKit та Google Play Billing, дає unified API, webhooks, аналітику когорт та A/B тести paywall.
Альтернатива RevenueCat — власна реалізація з Adapty або Qonversion. Повністю кастомна — тільки якщо дані не повинні залишати інфраструктуру або є нестандартна логіка. Ми гарантуємо, що налаштування webhooks та обробка подій життя підписки виконується без втрат — перевірено на проектах з аудиторією понад 500 тис. DAU.
Google Play Billing Library 6+ вимагає обробки PurchasesUpdatedListener та явного виклику acknowledgePurchase() або consumePurchase() протягом 3 днів — інакше Google автоматично скасовує покупку та повертає гроші. Середня вартість такої помилки — втрата значної суми на користувача на місяць (за даними наших проектів).
Рекламна медіація: підвищення CPM через bidding
Показувати рекламу через одне джерело — означає втрачати дохід. Медіація (waterfall або bidding) запитує рекламу у декількох мереж і показує найкращу ставку. Google AdMob — основа для banner, interstitial, rewarded. Медіація через AdMob Mediation або MAX (AppLovin) — другий де-факто стандарт. MAX використовує In-App Bidding — real-time аукціон без водоспаду. На практиці MAX дає CPM на 15-30% вище класичного waterfall (залежить від гео та аудиторії). У США для rewarded відео CPM може перевищувати певну суму. При 100 000 показів rewarded відео на день перехід з waterfall на In-App Bidding може приносити додатково значну суму щоденно.
ironSource (Unity Ads) — сильна позиція в ігровому сегменті, особливо rewarded video. Mintegral — добре закриває азійську аудиторію.
Налаштування медіації вимагає ATT (App Tracking Transparency) на iOS 14+. Без requestTrackingAuthorization рекламний CPM падає в 3-5 разів для користувачів, які не погодилися. SKAdNetwork та Privacy Manifest (iOS 17) — обов'язкові вимоги, без яких рев'ю падає.
| Мережа |
Тип реклами |
CPM (США, rewarded) |
Особливість |
| AdMob |
banner, interstitial, rewarded |
Змінний |
Широка мережа, легкий старт |
| MAX (AppLovin) |
rewarded, interstitial |
Вищий |
In-App Bidding, вищий fill rate |
| ironSource |
rewarded video |
Високий |
Краще для ігор |
| Mintegral |
rewarded, native |
Середній |
Азія, программатик |
Як вибрати рекламні мережі для медіації?
Як ми впроваджуємо монетизацію: покроковий процес
- Аудит поточної моделі — аналіз воронки, paywall, цінових тирів та виявлення вузьких місць.
- Проектування моделі — вибір типу (subscription, consumable, non-consumable) та оптимізація цінових точок.
- Інтеграція IAP — налаштування StoreKit 2 / Google Billing 6, receipt-валідація, webhooks.
- Рекламна медіація — підключення 3-6 мереж, налаштування waterfall або In-App Bidding, тестування fill rate.
- Аналітика та когорти — інтеграція RevenueCat, Amplitude або Firebase для відстеження LTV.
- A/B тестування paywall — використання Remote Config для експериментів без релізу.
- Запуск та моніторинг — 2 тижні безкоштовної підтримки після запуску, фікс багів по SLA 24 години.
Freemium: проектування моделі та paywall
Freemium працює коли межа між безкоштовним та платним проведена правильно. Занадто жорсткий paywall на старті — користувач видаляє. Занадто щедрий безкоштовний тир — немає стимулу платити.
Як проєктувати paywall для freemium?
Паттерн, який працює технічно: feature flags з сервера (Remote Config у Firebase або LaunchDarkly) керують доступом до фіч. Це дозволяє A/B тестувати paywall без релізу, змінювати умови тріалу, проводити акції.
Реалізація на рівні коду: EntitlementManager — єдина точка перевірки доступу до фіч, яка знає про статус підписки, флаги та промо. Жодних перевірок isPremium розкиданих по всьому коду. Досвід показує: такий підхід знижує кількість багів з paywall на 80% (підтверджено на 30+ проектах).
Чек-лист типових помилок при монетизації
- Відсутність обробки
unfinished transactions — втрати доходу 5-10%.
- Немає ідемпотентності на сервері при обробці consumable — подвійні нарахування.
- Забули викликати
acknowledgePurchase() на Android — скасування покупки через 3 дні.
- Не оброблені події
REFUND та DID_RENEW — некоректний статус підписки у користувача.
- Paywall без A/B тестів — залишають 20-40% потенціалу монетизації.
- Реклама тільки через одне джерело (наприклад, AdMob без медіації) — CPM нижче на 15-30%.
Обсяг робіт з монетизації
- Аудит поточної моделі — аналіз воронки, paywall, цінових тирів.
- Інтеграція IAP — StoreKit 2 / Google Billing 6, receipt-валідація, webhooks.
- Рекламна медіація — налаштування MAX / AdMob, підключення 3-6 мереж, тестування fill rate.
- Налаштування аналітики — RevenueCat, Amplitude / Firebase, когортний аналіз.
- Документація — опис ентайтлментів, процедура відновлення, чек-лист рев'ю.
- Навчання команди — розбір типових помилок, рекомендації з підтримки.
- Гарантія — безкоштовна підтримка 2 тижні після запуску, фікс багів по SLA 24 години.
Терміни орієнтовно
| Етап |
Тривалість |
| Базова IAP (один store) |
1–2 тижні |
| Підписочна система + RevenueCat + paywall |
3–5 тижнів |
| Рекламна медіація (MAX + 3 мережі) |
1–2 тижні |
| Повний цикл (IAP + реклама + аналітика) |
4–8 тижнів |
Вартість розраховується індивідуально. Ми працюємо в цій сфері більше 8 років і реалізували більше 40 проектів з монетизацією — багато з них пройшли App Store Review без жодного блокування. Зв'яжіться з нами для аудиту або замовте консультацію — розповімо, які точки зростання є у вашому додатку.
Джерела: Apple StoreKit 2 Documentation, RevenueCat Best Practices, Wikipedia: Freemium.