Playable не працює в Unity Ads: порожній екран
Playable працює локально, а в Unity Ads порожній екран: Unity прямо називає одну причину — посилання на асет. Ще сім перевірок зі специфікації.
PlayableMRAID7 хв читання

MRAID для playable: Unity вбудовує його сам. Каркас ready → viewableChange → старт і пауза → mraid.open по тапу на CTA, плюс запуск без MRAID.

MRAID — що це: набір обʼєктів і подій, через які HTML-реклама спілкується з вебвʼю рекламного SDK. Playable дізнається, що реклама готова й видна, і просить відкрити стор. В Unity Ads вебвʼю само вбудовує MRAID, тож тег зі скриптом MRAID у збірку додавати не треба. Нижче каркас: старт по ready, пауза по viewableChange і mraid.open лише по тапу на CTA після гри.
Розшифровка — Mobile Rich Media Ad Interface Definitions. По суті це домовленість: вебвʼю дає рекламі обʼєкт mraid, а реклама користується ним і сама в застосунок не лізе. Через нього playable робить чотири речі:
mraid.getState() — дізнається стан, наприклад loading;ready — отримує сигнал, що MRAID готовий;mraid.isViewable() і подія viewableChange — дізнається, чи видно рекламу зараз;mraid.open(url) — просить відкрити посилання, у нашому випадку сторінку в сторі.Що кажуть специфікації playable Unity: playable має підтримувати MRAID 3.0, вебвʼю Unity Ads вбудовує MRAID, а тег зі скриптом MRAID не потрібен. Unity Ads підтримує лише повноекранні MRAID 3.0 оголошення. Не підтримуються expand, resize, кастомні кнопки закриття, sms, tel, calendar і storePicture. Інші мережі можуть вимагати іншу версію, порівняння зібрано в статті вимоги до playable за мережами.
ready, або getState() уже не loading). Налаштовуємо playable і підписуємося на viewableChange.mraid.open.
Цей блок адаптовано з прикладу в доках Unity. Коментарі ми переклали та додали гілку без MRAID для десктопу. Самі startPlayable() і pausePlayable() Unity в прикладі лише викликає, не визначаючи.
// Адаптовано з прикладу в доках Unity (Playable specifications).
if (typeof mraid === "undefined") {
// Наше доповнення: збірку відкрито в десктопному браузері, MRAID немає.
startPlayable();
} else if (mraid.getState() === "loading") {
// Чекаємо на MRAID, потім налаштовуємо playable.
mraid.addEventListener("ready", onReady);
} else {
onReady();
}
function onReady() {
// Пауза й відновлення за видимістю реклами.
mraid.addEventListener("viewableChange", onViewableChange);
// Стартуємо, лише якщо реклама вже видна.
if (mraid.isViewable()) {
startPlayable();
}
}
function onViewableChange(viewable) {
if (viewable) {
startPlayable(); // старт або відновлення
} else {
pausePlayable(); // пауза й тиша
}
}
Ставте цей блок наприкінці скрипта, після оголошень стану з наступного розділу: let-змінні мають існувати до першого виклику startPlayable().
Це наша реалізація, у доках Unity її немає. Ідея: один стан paused, цикл анімації зупиняється по-справжньому, а повторний startPlayable() при вже запущеній грі нічого не робить. initGame, update, render, muteAudio та unmuteAudio — ваші функції.
let started = false;
let paused = true;
let raf = 0;
let last = 0;
function startPlayable() {
if (!paused) return; // уже йде
paused = false;
if (!started) {
started = true;
initGame(); // ваша сцена й обробники вводу
}
unmuteAudio();
raf = requestAnimationFrame(tick);
}
function pausePlayable() {
paused = true;
cancelAnimationFrame(raf);
last = 0; // після паузи не накопичуємо величезний інтервал між кадрами
muteAudio();
}
function tick(now) {
const dt = last ? now - last : 0;
last = now;
update(dt);
render();
raf = requestAnimationFrame(tick);
}
Якщо у вас є обробники вводу, починайте їх з if (paused) return;, інакше тап по схованій рекламі впливатиме на гру.
Unity радить Web Audio API як основний шлях, а HTMLAudioElement лише як запасний: він ігнорує mute-перемикач на iOS. Глушити й повертати звук Unity радить з обробника viewableChange, тому в каркасі це роблять виклики muteAudio() і unmuteAudio() усередині паузи та старту. Реалізацію звуку ми не наводимо: перевірте її на реальному iPhone з увімкненим mute-перемикачем і з блокуванням екрана.
Правило Unity: стор відкривається по тапу гравця на CTA після того, як він пограв. Перший тап відкрити стор не може, редиректи без дії гравця й оманливі редиректи (коли стор відкриває елемент геймплею) заборонені. Отже, кнопка з openStore живе лише на фінальному екрані. Блок нижче адаптовано з того самого прикладу Unity, адреси сторів у ньому — заглушки.
const STORE_URL = {
ios: "https://apps.apple.com/app/idyourgame",
android: "https://play.google.com/store/apps/details?id=yourgame",
};
function openStore() {
const ua = navigator.userAgent || navigator.vendor;
// Нові iPadOS у user agent пишуть Macintosh: шукаємо лише Android, решту вважаємо iOS.
const url = /android/i.test(ua) ? STORE_URL.android : STORE_URL.ios;
if (typeof mraid === "undefined") window.open(url, "_blank"); // десктопний тест
else mraid.open(url);
}
// ctaButton є лише на фінальному екрані, після гри.
ctaButton.addEventListener("click", () => {
if (!paused) openStore();
});
Best practices Unity просять переконатися, що фінальна збірка запускається й без MRAID: так можна протестувати весь playable в десктопному браузері. У каркасі за це відповідає гілка typeof mraid === "undefined" і запасний window.open в openStore. Відкрийте зібраний index.html у браузері й пройдіть гру до CTA з мобільною роздільною здатністю.
Далі потрібен реальний телефон: Unity пише, що десктопний браузер і симулятор не запускають playable в справжньому рекламному юніті, а багато причин реджекту видно лише на пристрої. Застосунок Ad Testing відкривається за QR-кодом, який дашборд генерує для кожного пака за кнопкою Show QR code. Перевірте, що гра ставиться на паузу й відновлюється по viewableChange, що CTA веде в правильний стор на iOS та Android і що поворот пристрою її не ламає. Якщо локально все працює, а в рекламі порожній екран, дивіться розбір порожнього екрана. Повний список вимог — у статті вимоги Unity Ads до playable.
startPlayable() і pausePlayable(): код вище наш, не Unity.У DarkCore Ramet є Playable Builder.
Каркас готовий, далі потрібен масовий залив
DarkCore Ramet запускає кампанії в Unity Ads пачками: оберіть апки та гео, подивіться превʼю, а черга відправить їх у темпі, який дозволяє Unity.
Playable працює локально, а в Unity Ads порожній екран: Unity прямо називає одну причину — посилання на асет. Ще сім перевірок зі специфікації.
PlayableMRAID7 хв читання

Playable для Unity Ads: один index.html до 5 МБ, base64, MRAID 3.0, без мережі, стор лише по тапу на CTA. Чек-лист за групами й що перевіряє модерація.
PlayableМодерація6 хв читання

Як зібрати HTML5-гру на Vite і Phaser в один index.html для Unity Ads: vite-plugin-singlefile, текстури з base64 і перевірка файлу за списком Unity.
PlayableКреативи6 хв читання
