GameDev Guide
Глава 2016 мин чтенияПроверено: 5 сентября 2026 г.

Частые причины отказа и как их закрыть

Разбор официального списка Яндекса — четырнадцать типовых нарушений с номерами требований, кодом исправления, механикой удвоения кулдауна и чек-листом самопроверки.

Содержание главы

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

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

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

Интерфейс

Контекстное меню при взаимодействии (1.6.1.8, 1.6.2.7)

Самое частое нарушение и самое дешёвое в исправлении. При правом клике или долгом нажатии в игровой области появляется системное контекстное меню браузера — его необходимо отключить.

const canvas = document.getElementById('game');

canvas.addEventListener('contextmenu', (e) => e.preventDefault());

Долгое нажатие на мобильных лечится не JS, а CSS:

#game, #game * {
  -webkit-touch-callout: none;   /* меню по лонгтапу в Safari */
  -webkit-user-select: none;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
}

Проверяется за пять секунд: правый клик по канвасу на десктопе, удержание пальца на картинке на телефоне.

Системный видеоплеер вместо игрового (1.6.1.6, 1.6.2.5)

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

Практически это значит: controls не ставить, playsinline ставить обязательно, элементы управления рисовать свои.

<video id="cutscene" playsinline muted preload="auto"></video>
const video = document.getElementById('cutscene');
video.setAttribute('playsinline', '');       // без этого iOS откроет системный плеер
video.setAttribute('webkit-playsinline', '');
video.controls = false;

Отдельно: встраивание YouTube-плеера не принимается (пункт 3.9).

Звук не ставится на паузу во время рекламы (4.7)

Во время показа рекламного ролика звук из игры продолжает играть. Требование 4.7 обязывает ставить на паузу и звук, и геймплей — на время interstitial и rewarded video.

Отдельно стоит помнить про стартовую рекламу: платформа показывает полноэкранный блок на старте всех игр автоматически, и колбэков у него нет. Единственный способ узнать о ней — события game_api_pause и game_api_resume.

ysdk.on('game_api_pause', () => { audioCtx.suspend(); pauseGame(); });
ysdk.on('game_api_resume', () => { audioCtx.resume(); resumeGame(); });

Проверка модератора: открыть игру в наушниках и ничего не трогать.

Звук продолжается при переключении вкладки (1.3)

Методика проверки описана в документации буквально. Звук должен останавливаться:

  • при сворачивании окна браузера на компьютере или приложения на телефоне;
  • после переключения на другую вкладку в том же окне;
  • в браузерном меню выбора вкладок.

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

document.addEventListener('visibilitychange', () => {
  document.visibilityState === 'hidden' ? suspendAll() : resumeAll();
});
window.addEventListener('blur', suspendAll);
window.addEventListener('focus', resumeAll);

SDK

Game Ready работает некорректно (1.19.2)

Метод ysdk.features.LoadingAPI.ready() подключён, но вызывается неправильно или не в тот момент жизненного цикла. Классические варианты: вызов сразу после YaGames.init(), когда ресурсы ещё грузятся; вызов после нажатия «Играть»; вызов внутри цикла загрузки.

Правильный момент один: все ресурсы загружены, все элементы интерактивны, загрузочных экранов не осталось.

const ysdk = await YaGames.init();
await loadAllAssets();     // картинки, звуки, шрифты
buildUI();                 // интерфейс собран и кликабелен
ysdk.features.LoadingAPI?.ready();

Game Ready не используется совсем (1.19.2)

Та же строка требования, отдельная строка в таблице отказов — настолько часто встречается. Метод обязателен для публикации в каталоге. На debug-панели индикатор Game Ready ждёт вызова 90 секунд, после чего краснеет и считается невызванным.

Автоопределение языка не реализовано (2.14)

«Язык интерфейса задаётся вручную вместо использования ysdk.environment.i18n.lang». Требование действует даже для игр с одним языком и вовсе без текстов, а определение должно происходить на старте, а не в процессе игры.

const lang = ysdk.environment.i18n.lang; // 'ru', 'en', 'tr' — ISO 639-1
applyLanguage(resolveLang(lang));

Проверяется по индикатору на debug-панели: он должен позеленеть во время загрузки.

SDK не встроен или встроен некорректно (1.1)

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

Актуальное подключение — относительный путь для игры, залитой архивом в Консоль:

<!-- Yandex Games SDK -->
<script src="/sdk.js"></script>

Для игры на собственном домене или в iframe — абсолютный https://sdk.games.s3.yandex.net/sdk.js.

Частая ошибка

Если ваше руководство, статья или ответ нейросети предлагают подключить SDK по адресу https://yandex.ru/games/sdk/v2 — это устаревший загрузчик. Игра будет работать: SDK инициализируется, реклама покажется, данные сохранятся. Но debug-панель покажет IF (Is loader: false), требование 1.19.1 будет не выполнено, и это отказ. Единственный способ убедиться — открыть игру с debug-mode=16 и увидеть IT.

Технические сбои

Прогресс не сохраняется (1.9)

Результаты, уровни или настройки не сохраняются между сессиями. Проверяется тривиально: пройти уровень и нажать F5.

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

Игра не запускается (1.14)

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

Отдельная категория — «экраны-тупики»: экран после проигрыша, с которого нельзя вернуться в меню или начать заново. Это тоже 1.14.

Ошибки JS в консоли (1.14)

«В консоли браузера появляются JS-ошибки при запуске или в ходе игры, которые влияют на работоспособность». Модератор держит DevTools открытыми.

Практическое следствие: каждый вызов SDK оборачивается в try/catch, каждый промис — в .catch(). Необработанное отклонение промиса — это красная строка в консоли.

window.addEventListener('unhandledrejection', (e) => {
  console.warn('[app] необработанный промис', e.reason);
  e.preventDefault(); // не роняем игру из-за сетевой ошибки
});

Заодно уберите из релизной сборки технические надписи и отладочные логи: в пояснениях к 1.14 есть примеры отказов из-за всплывающего технического текста и меню с неигровыми кнопками.

Игра зависает или тормозит (1.15)

«Заметные фризы или падение производительности делают игру некомфортной для пользователя». Формулировка самого пункта 1.15 при этом шире — про завершённость игры, а зависания и вылеты описаны в пункте 1.14. На практике обе строки означают одно: если на среднем устройстве игра дёргается, это отказ.

Что проверить: худший кадр в геймплее, поведение при повороте экрана и изменении размера окна, память после десяти минут игры.

Соответствие описанию

Игра не соответствует заявленному жанру (2.3)

Геймплей противоречит выбранной на вкладке «Черновик» категории. Возникает в двух случаях: категорию выбрали «пошире, чтобы охватить больше», или игра по ходу разработки превратилась во что-то другое, а черновик остался старым.

Правило: жанр должен быть очевиден модератору за первые тридцать секунд игры.

Вводящее в заблуждение название (8.2.2)

Название содержит слова, вводящие пользователя в заблуждение относительно условий игры: «free», «top», «best», «бесплатно», «бесплатный» и подобные. Все игры в каталоге бесплатные, поэтому «бесплатно» в названии — не информация, а обещание, которое ничего не обещает.

Само требование 8.2.2 шире запретного списка слов: тексты должны отражать реальную механику игры и её основной геймплей. Скриншот с механикой, которой в игре нет, — то же нарушение.

Кулдаун: почему вторая попытка дороже первой

Количество попыток не ограничено, но время ожидания перед повторной отправкой удваивается после каждого отклонения.

ОтклонениеОжидание перед следующей отправкой
После 1-го24 часа
После 2-го2 дня
После 3-го4 дня
После 4-го8 дней
После 5-го16 дней

Максимальное время ожидания — 384 часа (16 дней), дальше не растёт. Если исправление нужно внести экстренно, в Консоли есть кнопка Сброс кулдауна модерации — но воспользоваться ей можно не чаще, чем раз в 28 дней.

Важно

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

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

Чек-лист самопроверки

Прогоняется в режиме черновика с открытой debug-панелью и открытой консолью браузера. Порядок — от самого дешёвого к самому долгому.

  • Лоадер на debug-панели показывает IT, а не IF.
  • Индикатор Game Ready зелёный, время вызова разумное.
  • Индикатор зелёный: I18N is used.
  • Правый клик и долгое нажатие по игровому полю не открывают контекстное меню.
  • Видео (если есть) играет внутри игры, а не в системном плеере.
  • Стартовая реклама платформы не перекрывается вашей музыкой.
  • Во время interstitial и rewarded звук и геймплей на паузе.
  • Переключение вкладки и сворачивание окна останавливают звук.
  • Прогресс переживает F5 — и у авторизованного игрока, и у гостя.
  • После «Clear cloud data» игра корректно запускается с нуля.
  • В консоли нет ошибок ни при загрузке, ни после десяти минут игры.
  • Нет технических надписей, отладочных меню и текста «в разработке».
  • Игра не ломается при изменении размера окна и повороте экрана.
  • Из любого экрана есть выход: нет экранов-тупиков.
  • Категория соответствует тому, что видно в первые полминуты.
  • В названии нет «бесплатно», «лучшая», «топ», «free», «best», капса.
  • Скриншоты и видео показывают реальный геймплей этой игры.

Совет

Этот список удобно положить в CLAUDE.md проекта и попросить Claude Code проверить код по нему перед сборкой архива: часть пунктов (контекстное меню, playsinline, подписка на game_api_pause, обработка unhandledrejection, подключение /sdk.js) проверяется прямо по исходникам, без запуска игры.

Что дальше

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

Источники

Официальная документация платформы — единственный источник истины по её требованиям.

Нужно подробнее?

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

Что входит в полное обучение