Поставка софта Дистрибуция игр: магазины, консоли, рейтинги, региональные цены
0%

Дистрибуция игр: магазины, консоли, рейтинги, региональные цены

Дистрибуция игр: магазины, консоли, рейтинги, региональные цены

Дата релиза объявлена за четыре месяца, ролик собрал просмотры, предзаказы открыты. За семь недель до даты приходят три письма подряд. Первое: сертификация платформы вернула сборку с шестью замечаниями, два из них — про поведение при отключении контроллера. Второе: совет по классификации в одном из регионов поставил категорию выше ожидаемой из-за ответа про случайные предметы в анкете, и витрина там закрывается для части аудитории. Третье: бухгалтерия спрашивает, что делать с потоком ключей, которые кто-то скупает на дешёвом рынке и перепродаёт на дорогом.

Ни одна из трёх проблем не про геймплей, и ни одна уже не решается кодом: дата зафиксирована обещаниями, а между вашей сборкой и игроком стоят два внешних арбитра, каждый со своим сроком и правом сказать «нет».

Игры не поставляются по особым законам. Они поставляются по тем же законам, что и любой другой софт, но все ограничения трека включаются одновременно, на одном артефакте и к одной календарной дате. Поэтому дистрибуция игр — глава внутри трека, а не отдельная дисциплина: здесь каждая тема предыдущих глав встречается в самом жёстком своём варианте.

Эта глава продолжает Магазины приложений и предполагает, что механика прав и денег из Ценообразования и Биллинга уже знакома. Ниже — только то, что в играх устроено иначе или дороже.

Что в играх становится жёстче: карта соответствий

Общая тема трека Обычный софт Игры
Канал (08) свой сайт возможен как основной магазин практически безальтернативен для охвата, свой сайт — дополнение
Ревью площадки (09) задержка релиза задержка релиза при зафиксированной публично дате и оплаченной рекламе
Право пользования (07) подписка на сервис решётка прав: издание, дополнения, сезонный пропуск, внутриигровые товары
Ценообразование (06) одна цена и тарифы цена на каждый рынок отдельно, плюс арбитраж между рынками
Соответствие требованиям (13) персональные данные, юрисдикции плюс возрастная классификация и правила о случайных предметах
Обновления (11) выкатили новую версию патч проходит сертификацию заново, а старая версия не может играть с новой
Упаковка (12) пакет или образ депоты, ветки, дельта-патчи в десятки гигабайт

Из таблицы виден главный практический вывод: в играх нет «сначала выпустим, потом разберёмся». Разбираться придётся до подачи, потому что каждая итерация стоит недели календаря, а календарь уже продан аудитории.

Игра как единица поставки: не артефакт, а решётка прав

«Продать игру» звучит как одна транзакция. В системе это как минимум пять разных сущностей, и путать их дорого.

  • Продукт — то, что вы делаете. У продукта нет цены.
  • SKU (товарная позиция) — то, что лежит на витрине: стандартное издание, расширенное издание, дополнение, набор внутриигровой валюты, сезонный пропуск. У SKU есть цена, возрастная категория и список регионов.
  • Право пользования (entitlement) — факт того, что конкретный аккаунт владеет конкретным SKU. Именно право отзывается при возврате и именно его проверяет игра.
  • Событие выдачи — почему право появилось: покупка, ключ, подарок, подписочный каталог, компенсация от поддержки. Разные источники — разные правила возврата и разные комиссии.
  • Инвентарь — то, что игрок получил внутри игры вследствие права. Это ваш учёт, не платформы.

Три следствия, каждое из которых обычно узнают на практике.

Право живёт в аккаунте платформы, а не в вашем. Игрок, купивший игру, для вас анонимен: у вас есть идентификатор платформы и билет для проверки, но не почта и не платёжные данные. Значит, написать покупателю напрямую вы не можете, а свой аккаунт (если он нужен для кроссплатформенности или прогресса) придётся заводить отдельно и объяснять игроку, зачем — это отдельная воронка с отдельной конверсией.

Право отзываемо, инвентарь — нет. Возврат снимает право на дополнение, но предметы, которые игрок за это время получил и потратил, уже разошлись по экономике игры. Решение принимается заранее и записывается: либо инвентарь тоже сворачивается (и тогда нужна операция компенсации при отрицательном балансе), либо не сворачивается (и тогда возврат — это подарок, который надо ограничить по частоте).

Владение проверяется офлайн. Игрок в поезде должен запускать купленное. Клиент платформы отдаёт подписанный список прав с ограниченным сроком годности, игра проверяет подпись и работает по кэшу. Отсюда правило: офлайн-проверка отвечает только на вопрос «можно ли запускать», серверные вещи — прогресс, покупки, мультиплеер — требуют подтверждения на вашей стороне.

Обратите внимание на последние две строки: вебхук о возврате приходит асинхронно и может прийти дважды — это норма протокола, а не сбой. Идемпотентность обработки разобрана в распределённых системах, здесь она обязательна с первого дня.

Магазин на ПК: одновременно канал и рантайм

Главное отличие игровых площадок от магазинов приложений: площадка — не только витрина. SDK даёт список прав, облачные сохранения, достижения, друзей и приглашения, подбор игроков, серверы обмена трафиком, мастерскую пользовательского контента, оверлей. Отказаться можно, но тогда каждый пункт придётся построить самому. Цена владения этой зависимостью выглядит так:

Что даёт покупателю Во что обходится поставщику Какие обязательства создаёт
Одна библиотека, один аккаунт, автообновления, знакомые правила возврата интеграция с SDK и его версиями; сборка привязана к рантайму площадки; часть кода становится непереносимой сохранения, достижения и списки друзей превращаются в ожидания игрока: убрать их в следующей игре нельзя без объяснений
Скидки, списки желаемого, обзоры и видимость на витрине комиссия; правила витрины и правила скидок; обязанность отвечать на обзоры и обращения ваша страница на витрине — публичное лицо, за которое отвечаете вы, а модерирует площадка
Мультиплеер «из коробки» через сервисы площадки привязка сетевого стека к платформе, сложность кроссплатформенной игры если сервисы площадки лежат, лежит ваш мультиплеер, а объясняться с игроками вам

Технически поставка на такой площадке устроена вокруг депотов (наборов файлов, каждый со своей платформой и языком) и веток (билд-каналов, куда депоты собираются в конфигурацию). Схема ровно та же, что каналы обновлений в главе 11, просто с игровыми словами.

# Загрузка сборки в закрытую ветку: её видят только те, у кого есть пароль ветки.
# Публикация в ветку по умолчанию — отдельное решение человека,
# а не автоматическое следствие зелёной сборки.
steamcmd +login "$BUILD_ACCOUNT" \
         +run_app_build /build/scripts/app_build_1234567.vdf \
         +quit

Практическое правило: ветка по умолчанию никогда не обновляется из конвейера напрямую. Конвейер публикует в закрытую ветку, человек переключает. Причина не в недоверии к конвейеру, а в том, что откат публикации на площадке — не git revert, а повторная загрузка предыдущей сборки, которую все игроки будут качать заново.

Ключи как отдельный канал со своей ценой

Площадки на ПК обычно позволяют генерировать ключи активации и продавать их где угодно — комиссии площадка за это, как правило, не берёт, потому что деньги идут мимо неё. Выглядит как способ обойти комиссию, но у канала своя цена.

  • Ключ — это уже выданное право без денег. Пока ключ не активирован, у вас обязательство без выручки. Партнёр, взявший тысячу ключей, может не заплатить, а ключи уже живые.
  • Возвратный риск смещается на вас. Ключи, купленные по украденным картам, оборачиваются спорными операциями у перепродавца. Площадка отзывает такие ключи, игра пропадает у людей, которые честно за неё платили перепродавцу, и они приходят к вам.
  • Ключи ломают ценовую политику. Ключ активируется в любом регионе (если вы не ограничили активацию), поэтому он мгновенно переносит самую низкую цену на самый дорогой рынок.
  • Ключи не дают вам отношений с покупателем — как и сама площадка, но при этом ещё и не дают комиссии площадки в обмен на витрину.

Разумное применение: пресса и стримеры, наборы и благотворительные акции, партнёрские дистрибуторы с договором, компенсации от поддержки. Как основной способ продавать — редко.

Возврат в играх: время как критерий

Игровые площадки почти всегда используют комбинированный критерий: возврат без объяснений в пределах небольшого числа дней с покупки и ограниченного наигранного времени (порядок величин на август 2026 года — около двух часов и около двух недель, у разных площадок по-разному, проверяйте текущие правила по документации). Это работает как «пробный период задним числом» и порождает три инженерных требования:

  1. Считать наигранное время честно. Площадка считает своё, вы считаете своё; расхождение между ними станет предметом спора в поддержке.
  2. Понимать, что короткие игры бьются об это правило. Игра на полтора часа возвращается после прохождения полностью законно. Ответ — не жалобы, а структура продукта: либо больше контента, либо цена, при которой возврат невыгоден по трудозатратам, либо эпизодическая модель.
  3. Отзывать право, а не только останавливать деньги. Механика отзыва — та же, что в главе о биллинге: состояние права, событие отзыва, инвалидация кэшей.

Комиссии: механизм и порядок величин, а не таблица процентов

Любая таблица процентов устареет раньше, чем вы дочитаете статью: ставки меняются решениями площадок, судов и регуляторов. Устойчиво только знание того, из чего складывается удержание.

В играх слоёв больше, чем в обычном софте, и это ключевое отличие:

  1. Налог в цене на витрине. На большинстве рынков цена показывается вместе с налогом, и налог не ваш.
  2. Доля площадки. Не константа: зависит от типа товара (базовая игра, дополнение, внутриигровая покупка, подписка), от накопленной выручки на площадке и от участия в программах для небольших команд.
  3. Роялти движка. Коммерческие движки берут процент с валовой выручки после порога — это не комиссия площадки, но считается так же и вычитается сверх неё.
  4. Доля издателя. Если издатель есть, он берёт свою долю от того, что дошло, и обычно сначала возвращает вложенное (возврат аванса).
  5. Средний и посреднический слой. Плата за портирование, за локализацию, за возрастную классификацию, за сертификацию — это не проценты, а фиксированные суммы, но в юнит-экономике они живут рядом.

Порядок величин на август 2026 года: доля крупных игровых площадок — десятки процентов, чаще всего около 30 с понижением для отдельных категорий и объёмов; отдельные площадки конкурируют ставкой в районе 12 процентов; роялти движков — единицы процентов от валовой выручки после порога в сотни тысяч единиц валюты; доля издателя договорная и разбросана широко. Единственный источник, которому имеет смысл верить, — текущая документация конкретной площадки и ваш договор.

Считать надо не объявленные ставки, а то, что доезжает. Пусть $P$ — цена на витрине с налогом, $\tau$ — ставка налога в цене, $r$ — доля возвратов, $c$ — доля площадки, $\rho$ — роялти движка от валовой выручки, $\sigma$ — доля издателя:

$$ G = \frac{P}{1 + \tau}, \qquad N = G \cdot (1 - r) \cdot \lbrack (1 - c) - \rho \rbrack \cdot (1 - \sigma) $$

Подставим: цена на витрине 2000 рублей, налог в цене 20 процентов, возвраты 6 процентов, доля площадки 30 процентов, роялти движка 5 процентов, доля издателя 30 процентов.

  • база: 2000 / 1,2 = 1667 рублей;
  • после возвратов: 1567 рублей;
  • после площадки и роялти: 1567 · (0,70 − 0,05) = 1019 рублей;
  • после издателя: 713 рублей.

Из двух тысяч рублей на витрине до команды доезжает около семисот. Это не повод обижаться на площадку — это исходные данные для планирования: чтобы окупить бюджет в десять миллионов рублей, нужно не пять тысяч копий, а около четырнадцати тысяч. Ошибка в этом расчёте — самая частая причина, по которой «игра хорошо продалась, а денег нет».

Считать это надо в целых минорных единицах (копейках) с единственным округлением в конце — правило из Биллинга действует и здесь. И сравнивать надо не объявленные ставки, а эффективную: сумма всех удержаний за квартал, делённая на валовые начисления, после возвратов. Объявленная всегда ниже фактической, и разница — ровно то, чего не хватает в модели.

Порог, за которым имеет смысл свой канал вместо площадки, выведен в карте трека и в главе о каналах; в играх к нему добавляется грубая поправка: свой канал не даёт видимости, а видимость на игровых витринах — это заметная часть продаж. Считать надо не только комиссию, но и стоимость привлечения игрока, которую площадка берёт на себя (юнит-экономика).

Консоли: закрытая платформа, договор и сертификация

Консоль — самый закрытый канал в этом треке: договор с производителем платформы, обычно под соглашением о неразглашении, комплект разработчика (специальное устройство) и техническая сертификация каждой сборки, включая патчи. Разберём по той же рамке цены владения.

Что даёт покупателю. Гарантию совместимости: игра запустится и не сломает систему, интерфейс одинаков во всех играх, покупки и права работают предсказуемо, родительский контроль действительно контролирует. Консоль продаёт именно эту предсказуемость.

Во что обходится поставщику. Отдельная сборка под закрытый SDK; тестирование на устройстве, которое нельзя купить в магазине; выполнение технических требований платформы (обработка отключения контроллера, смены пользователя, потери сети, спящего режима, ограничений на память и время загрузки, требований к терминологии интерфейса); отдельный цикл подачи и ожидания; NDA, из-за которого нельзя обсуждать проблему на публичном форуме и приходится идти в закрытый портал разработчика.

Какие обязательства создаёт. Каждый патч — снова сертификация. Срочное исправление не выкатывается за час: есть ускоренные процедуры, но они — исключение, которое надо обосновать. Требования платформы меняются, и старая игра однажды перестаёт им соответствовать. Снятие с продажи по вашей инициативе тоже регламентировано.

Из этой диаграммы вытекает знаменитый патч первого дня. Мастер-сборку нужно подать заранее: на сертификацию, на изготовление физических носителей, на подготовку витрины. Разработка за это время не останавливается. К дню релиза накапливаются исправления, которые уезжают отдельным патчем. Это не разгильдяйство, а следствие календаря — но обязательство остаётся: игра на диске без сети должна быть играбельной, потому что часть покупателей не скачает патч никогда.

Типичные причины отказа — не «игра плохая», а нарушения контракта платформы: падение при выдёргивании контроллера или смене пользователя, некорректное поведение при потере соединения посреди покупки, неправильная терминология на экранах аккаунта, запись сохранений не туда, несоответствие заявленной возрастной категории, превышение лимитов на размер обновления. Всё это проверяемо заранее по чек-листу требований платформы, и прогон чек-листа своими силами до подачи экономит недели — он должен быть частью конвейера (devops).

Отдельно про лицензии зависимостей

Правила магазинов и консолей накладывают на получателя дополнительные ограничения: привязку к аккаунту, лимит устройств, запрет на модификацию. Сильный копилефт этого не допускает — отсюда известные истории со снятием приложений с продажи после обращений правообладателей GPL-кода. На портале есть свой пример того же механизма, только мягче: инстанс it-tools под GPL-3.0 отдаёт браузеру собранный бандл, то есть объектный код, и потому обязан сопровождаться ссылкой на исходники ровно этой версии. В игре триггер тот же — передача объектного кода получателю, — а последствие жёстче: лицензия одной библиотеки может закрыть целый канал. Проверять зависимости надо до подачи, а не после отказа (Лицензии, цепочка поставок). Отдельный слой — движок и middleware: разрешительные по коду, но платные по роялти и требующие логотипов и упоминаний в титрах, что тоже обязательство поставки.

Возрастная классификация: анкета как конфигурация продукта

Возрастной рейтинг в голове разработчика — картинка на обложке. В системе поставки это конфигурация, от которой зависят доступные вам рынки. Механика везде похожа: вы заполняете анкету о содержании — насилие и его натурализм, сексуальный контент, лексика, наркотики, азартные игры и их имитация, страх, дискриминация, покупки внутри игры, случайные предметы, пользовательский контент и общение между игроками. Система вроде IARC по одной анкете выдаёт набор категорий разных советов сразу (ESRB, PEGI, USK, CERO, ClassInd, ACB и другие): советы оценивают одни и те же ответы по разным шкалам. Для отдельных рынков классификация выдаётся не автоматически, а по отдельной процедуре, иногда платной и небыстрой.

Три вещи, которые надо понять инженеру.

Анкета — про факты, а не про впечатление. Ответ «есть элементы случайности в покупках» включает набор требований площадок, а в некоторых юрисдикциях — дополнительных ограничений. Соблазн ответить помягче понятен и опасен: последствие — не спор о вкусах, а переклассификация задним числом и снятие с продажи.

Анкета живёт вместе с контентом. Патч, добавляющий кровь, азартный мини-режим или голосовой чат, меняет ответы. Значит, декларация контента должна быть версионируемым артефактом рядом с кодом, а не письмом в переписке.

# Декларация контента: единственный источник правды для анкет классификации.
# Лежит в репозитории, меняется через ревью, версия попадает в релизные заметки.
content_declaration:
  version: 7
  applies_to_builds: "1.4.0 .. 1.4.x"
  violence:
    depicted: true
    realistic_human_target: false
    blood: "stylised"          # формулировки берутся из анкеты, а не придумываются
  in_game_purchases:
    present: true
    random_items: true         # ключевой ответ: включает отдельные требования площадок
    odds_disclosure_url: "https://example.com/odds"
  user_generated_content:
    present: true              # голосовой и текстовый чат — это тоже UGC
    moderation: ["profanity_filter", "report_flow", "server_side_mute"]
  gambling_simulation: false
  reviewed_by: "release-board-2026-03-02"

Пользовательский контент делает рейтинг условным. Если игроки могут общаться или создавать контент, содержание игры перестаёт быть детерминированным. Площадки отвечают на это требованием средств модерации: фильтр, жалоба, блокировка, возможность отключить общение, отдельные ограничения для несовершеннолетних аккаунтов. Это не «фича по остаточному принципу», а условие допуска на витрину — планируйте её как обязательную часть продукта наряду с сохранениями.

Возрастная маркировка — это ещё и требование к самому продукту и к его рекламе в каждой юрисдикции: где-то нужна маркировка на витрине и в материалах, где-то — экран с указанием категории при запуске, где-то — ограничения на показ рекламы. Какие именно требования применяются к вашей игре на конкретном рынке — вопрос к юристу, и ниже сказано, как его сформулировать, чтобы ответ был полезным.

Региональные цены: почему это не курс, умноженный на цену

Наивная модель: взять цену на домашнем рынке, умножить на курс, показать. Она ломается сразу по четырём причинам.

  1. Покупательная способность. Одна и та же сумма в пересчёте по курсу означает разную долю месячного дохода. Цена, выставленная по курсу, на части рынков просто не продаётся.
  2. Локальные ценовые точки. В каждой валюте есть привычные цены — «красивые» окончания и ступени. Цена, полученная умножением, выглядит как ошибка и снижает конверсию.
  3. Налог внутри цены. На витринах, показывающих цену с налогом, одна и та же база даёт разную цифру на ценнике в разных странах, и наоборот.
  4. Конкуренция и история рынка. На рынке уже сложился уровень цен на похожие игры, и он может не иметь отношения ни к курсу, ни к доходам.

Отсюда следует главное инженерное требование: цена — это не поле в таблице товара, а таблица фактов с интервалами действия.

-- Цена — факт с интервалом действия, а не атрибут товара.
CREATE TABLE sku_price (
    sku_id         text        NOT NULL,
    region         text        NOT NULL,     -- рынок витрины, а не страна игрока
    currency       char(3)     NOT NULL,     -- код по ISO 4217
    amount_minor   bigint      NOT NULL CHECK (amount_minor > 0),
    effective_from timestamptz NOT NULL,
    effective_to   timestamptz,              -- NULL — действует сейчас
    reason         text        NOT NULL,     -- 'launch' | 'fx_review' | 'permanent_cut'
    approved_by    text        NOT NULL,     -- решение принимает человек, и он назван
    PRIMARY KEY (sku_id, region, effective_from)
);

-- Цена заказа фиксируется в момент оформления и больше не пересчитывается:
-- предзаказ, оформленный до пересмотра, остаётся по старой цене.
-- Это не «доброта», а требование к учёту: иначе выручку нельзя воспроизвести.

Сам подбор цены удобно свести к трём шагам, каждый из которых считается отдельно и обсуждается отдельно: базовая цена умножается на индекс покупательной способности рынка, переводится по курсу, притягивается к ближайшей привычной для этой валюты ценовой точке (окончания вроде 90 или 99, целые единицы в валютах без дробной части). Стоимость этого расчёта — O(1) на рынок, вся настоящая стоимость в согласовании: результат — предложение для человека, а не публикуемая цена, и в таблицу выше он попадает вместе с именем того, кто его утвердил.

Арбитраж: почему разрыв цен нельзя делать любым

Как только цены на разных рынках различаются, появляется бизнес: купить там, где дёшево, продать там, где дорого. Этим занимаются и отдельные игроки, и целые сайты перепродажи ключей.

Региональные цены и порог арбитража: разрыв между рынками, условие перепродажи и механизмы защиты

Условие, при котором перепродажа выгодна, простое: разница цен больше суммарных издержек посредника — комиссии площадки перепродажи, стоимости перевода права между аккаунтами и платы за риск того, что право отзовут. Управлять можно каждым слагаемым:

  • ограничение активации — право работает только в регионе покупки (жёстко, бьёт по честным игрокам, которые переехали или путешествуют);
  • регион по способу оплаты, а не по адресу подключения — снижает эффективность обхода через туннели, не задевая обычных игроков;
  • ограничение подарков и передачи прав — увеличивает стоимость перевода;
  • сближение цен соседних рынков — самый скучный и самый действенный способ: если разрыв меньше издержек перепродажи, бизнеса просто нет.

Важно понимать цену каждого решения. Жёсткая привязка к региону — это поток обращений в поддержку от людей, которые переехали, и репутационный удар. Полное отсутствие ограничений — это перенос самой низкой цены на весь мир. Выбор здесь всегда компромисс, и он должен быть осознанным, а не следствием настроек по умолчанию.

Когда курс уехал

Пересмотр региональной цены — событие, а не правка в таблице. Разумный механизм:

  • Порог, а не реакция на каждое движение. Пересматриваем, если отклонение курса от заложенного держится дольше заданного срока (скажем, месяц) и превышает заданную величину. Метания за курсом разрушают доверие быстрее, чем любая цена.
  • Разделение видов изменений. Повышение цены — публичное событие: предупреждение заранее, окно, в которое действует старая цена, объяснение. Понижение — тоже событие, но с другой проблемой: те, кто купил вчера, спросят про компенсацию, и ответ должен быть готов до, а не после.
  • Правила площадки поверх ваших. Многие площадки ограничивают частоту изменения цены и запрещают повышать её перед распродажей. Ваш календарь цен обязан жить в тех же рамках.
  • Уже оформленные заказы не пересчитываются. Ни в плюс, ни в минус — иначе бухгалтерский учёт перестаёт сходиться с витриной.

Скидки и распродажи как обязательство

Скидка выглядит как маркетинг, а ведёт себя как релиз: дата, длительность, почти невозможный откат и правила площадки поверх ваших (минимальный интервал между скидками, минимальный срок с релиза, запрет повышать цену рядом со скидкой, ограничения на глубину). Инженерная часть, о которой забывают: скидка и цена — разные сущности. Скидка не меняет базовую цену, а добавляет временное правило поверх неё. Реализованная как «поправить цену, потом вернуть обратно», она оставляет в истории цен ложное повышение: площадка это заметит, а вы не отличите окончание скидки от подорожания.

Три календаря, которые не складываются

Релиз игры — это пересечение трёх независимых расписаний: ваш контент, классификация, сертификация платформы. Ни одно из них вы не контролируете полностью, а маркетинговая дата объявлена раньше всех трёх.

Читать эту диаграмму надо не как план, а как источник трёх правил.

  1. Между мастер-кандидатом и релизом закладывается не одна подача, а две. Первая подача с замечаниями — нормальный, а не аварийный исход.
  2. Классификация начинается раньше кода. Она зависит от описания контента, а не от готовой сборки, и её можно вести параллельно — но её результат влияет на список рынков, то есть на цены и на маркетинг.
  3. Патч первого дня планируется заранее как часть релиза, с собственным окном сертификации.

Отсюда практика, которая экономит больше всего нервов: функциональные флаги. Спорная функция, которую могут не пропустить, должна выключаться конфигурацией без новой сборки — иначе отказ означает полный цикл заново. Механика флагов и безопасных релизов — в SRE.

Деньги внутри игры

Внутриигровые покупки — это ценообразование по потреблению, только с двумя добавками: покупатель часто несовершеннолетний, а товар часто случайный.

Инженерный минимум, ниже которого начинаются потери:

  • Сервер — единственный источник правды по балансу и инвентарю. Клиент сообщает о покупке, но ничего не решает; иначе первая же модифицированная сборка раздаёт всё бесплатно.
  • Выдача идемпотентна. Подтверждение платформы может прийти дважды, клиент может повторить запрос, сеть может оборваться посреди операции.
  • Восстановление покупок обязательно. Игрок переустановил игру или сменил устройство — он должен получить купленное без обращения в поддержку.
  • Внутриигровая валюта — обязательство, а не выручка. Купленные, но не потраченные монеты — это ваш долг перед игроком, который надо учитывать отдельно; правила признания такой выручки отличаются от разовой продажи, и это вопрос к бухгалтеру, а не к разработчику.
def grant_from_platform_receipt(receipt: dict) -> None:
    """Выдача внутриигрового товара по подтверждению площадки.

    Порядок важен: сначала проверяем подпись платформы, потом фиксируем факт выдачи
    по ключу идемпотентности, и только потом меняем инвентарь.
    """
    verify_platform_signature(receipt)          # доверяем платформе, а не клиенту
    txn_id = receipt["platform_transaction_id"]
    with db.transaction():
        inserted = db.execute(
            "INSERT INTO grant_log (platform_txn_id, account_id, sku_id, state) "
            "VALUES (%s, %s, %s, 'granted') "
            "ON CONFLICT (platform_txn_id) DO NOTHING",
            (txn_id, receipt["account_id"], receipt["sku_id"]),
        ).rowcount
        if inserted == 0:
            return                              # повтор: второй раз не начисляем
        add_inventory(receipt["account_id"], receipt["sku_id"])

Отдельная тема — случайные предметы. Требования площадок здесь ужесточались несколько раз подряд, и общее направление устойчиво: раскрывать вероятности выпадения, отделять покупку от азартной механики в интерфейсе, ограничивать доступ несовершеннолетним. В части юрисдикций такие механики регулируются отдельно, вплоть до запрета. Практический вывод для инженера: вероятности должны быть данными, а не константами в коде — их надо публиковать, версионировать и уметь показать за любую прошедшую дату.

Родительский контроль порождает свой класс возвратов: покупки, сделанные ребёнком, возвращаются чаще и на больших суммах. Это не мошенничество, а нормальный режим работы платформы, и его надо закладывать в модель возвратов, а не считать аномалией.

Что здесь вопрос к юристу и как его задать

Ничего в этой главе не является юридической консультацией. Ниже — перечень вопросов, где нужен именно юрист, и формулировки, с которыми к нему идти: правильно заданный вопрос экономит недели.

  • Возрастная маркировка на рынке. Не «какой у нас рейтинг», а: «вот декларация контента версии 7 и полученные категории советов; какие требования по маркировке на витрине, в рекламе и внутри продукта возникают на рынках X, Y, Z и кто за них отвечает — мы или площадка».
  • Случайные предметы и внутриигровая валюта. «Механика устроена так-то (описание и вероятности); подпадает ли она под ограничения на рынках X и Y и какие раскрытия обязательны».
  • Договор с платформой. «Вот проект соглашения; какие обязательства он создаёт по срокам поддержки, снятию с продажи, возвратам и нашей ответственности за пользовательский контент».
  • Налоги и статус площадки. «Площадка — продавец для конечного покупателя или агент? Что это меняет для нас в части налогов и документов». Ответ разный у разных площадок, и от него зависит вся бухгалтерская часть.
  • Пользовательский контент и персональные данные игроков. Отдельная большая тема: Ограничения и приватность в треке безопасности.

Как обязательства выглядят записанными, видно на этом портале: оферта, правила возврата, политика ПДн. Это не шаблон для игры, а образец жанра: видно, какие вопросы обязаны иметь письменный ответ.

Патчи, размеры и совместимость

Подробности — в Обновлениях и Упаковке; здесь три игровых особенности.

Размер обновления — метрика продукта. Дельта-патч на сотни мегабайт и «перекачайте сорок гигабайт» — это разный отток. Компоновка файлов в депоты, стабильный порядок ресурсов и отказ от переупаковки всего архива при мелком изменении — работа с удержанием, а не микрооптимизация.

Мультиплеер делает обновление обязательным. Не обновившийся игрок не может играть с обновившимися: нужны версия протокола, понятное сообщение вместо загадочной ошибки подключения и окно поддержки обеих версий — обновление идёт волнами, потому что сертификация у платформ заканчивается в разные дни.

Откат сложнее, чем в вебе. Серверную часть откатить можно, уже скачанный клиент — нет. Изменения, ломающие совместимость сохранений, требуют плана миграции вперёд: неоткатываемая миграция превращает любой дефект в катастрофу.

Типичные ошибки

  1. Считать выручку по цене на витрине. Модель без налогов, комиссии, роялти и возвратов врёт в разы; движок в ней тоже не бесплатный.
  2. Планировать одну подачу на сертификацию и не закладывать патч первого дня. Первая подача с замечаниями — норма, а патч будет всё равно: вопрос лишь в том, есть ли у него окно.
  3. Отвечать на анкету классификации «помягче». Расхождение вскрывается позже и стоит рынка.
  4. Считать региональные цены умножением на курс. Получаются нерабочие цены и подарок перепродавцам.
  5. Продавать ключи как основной канал. Экономия на комиссии оборачивается спорными операциями, отозванными правами и разрушенной ценовой политикой.
  6. Реализовывать скидку как изменение базовой цены. История цен становится ложной, а правила площадки — нарушенными.
  7. Доверять клиенту в вопросах инвентаря и баланса. Первая же модифицированная сборка превращает экономику в ноль.
  8. Публиковать в основную ветку прямо из конвейера. Откат публикации — это повторная закачка у всех игроков.
  9. Забыть про офлайн. Игра на физическом носителе без сети должна запускаться и играться.
  10. Оставить чат и пользовательский контент без средств модерации. Это условие допуска на витрину, а не пожелание.

Мини-итог

  • Игры — не отдельная дисциплина поставки, а её предельный случай: все ограничения трека сразу, на одном артефакте, к жёсткой дате.
  • Единица поставки — не файл, а решётка прав. Право живёт в аккаунте платформы, отзывается возвратом и проверяется офлайн по подписанному кэшу; инвентарь — уже ваш учёт.
  • Магазин на ПК — одновременно канал и рантайм: вместе с продажами вы берёте зависимость от сервисов площадки и обязательства перед игроками, которые к ним привыкли. Ключи — не способ обойти комиссию, а отдельный канал со своими рисками.
  • Комиссию нельзя знать по таблице, её считают по механизму: налог в цене, доля площадки, роялти движка, доля издателя, возвраты. Из двух тысяч рублей на витрине до команды доезжает порядка семисот.
  • Консоль — закрытая платформа: договор, комплект разработчика, сертификация каждой сборки и патча. Патч первого дня — следствие календаря, но игра без сети обязана быть играбельной.
  • Возрастная классификация — конфигурация продукта: анкета определяет доступные рынки, живёт в репозитории рядом с кодом и меняется вместе с контентом.
  • Региональная цена — решение по каждому рынку с фиксацией в истории цен, а не умножение на курс. Разрыв цен должен быть меньше издержек перепродажи, иначе вы финансируете чужой бизнес.
  • Всё, что начинается со слов «а можно ли по закону», — вопрос к юристу, и задавать его надо с декларацией контента, описанием механик и проектом договора в руках.

Источники

Что дальше

Игра вышла, и в тот же момент множество запущенных версий перестало быть единственным: у кого-то стоит релизная сборка, у кого-то патч первого дня, у кого-то консоль без сети. Как управлять этим множеством — каналы обновлений, откат, поддержка старых версий и разговор с теми, кто обновляться не хочет, — в следующей главе.

Обновления и версии: каналы, откат, поддержка старых

Нашли неточность? Выделите фрагмент текста — рядом появится жучок.

Нужен разбор именно вашей ситуации?

Статья описывает общий случай. Если у вас частный — можно разобрать его отдельно, платно. А если не хватает целого материала, предложите тему: её оплачивают вскладчину, и она выходит открытой для всех.

Доска запросов