Перейти до вмісту

Що таке MRAID: каркас playable під Unity Ads

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

Опубліковано
5 хв читання
5 хв читання
English
Русский
У статті
  1. MRAID на пальцях
  2. Порядок подій у каркасі
  3. Код: ready і viewableChange
  4. startPlayable і pausePlayable
  5. Звук
  6. mraid.open лише по тапу на CTA
  7. Перевірка: збірка без MRAID запускається в десктопному браузері
  8. Чого в доках немає

MRAID — що це: набір обʼєктів і подій, через які HTML-реклама спілкується з вебвʼю рекламного SDK. Playable дізнається, що реклама готова й видна, і просить відкрити стор. В Unity Ads вебвʼю само вбудовує MRAID, тож тег зі скриптом MRAID у збірку додавати не треба. Нижче каркас: старт по ready, пауза по viewableChange і mraid.open лише по тапу на CTA після гри.

MRAID на пальцях

Розшифровка — 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 за мережами.

Порядок подій у каркасі

  1. Сторінка завантажилася. Гра не стартує: за документацією Unity, контент, що йде до того, як реклама видна, зʼїдає перші секунди гравця й виглядає зламаним.
  2. MRAID готовий (ready, або getState() уже не loading). Налаштовуємо playable і підписуємося на viewableChange.
  3. Реклама видна. Стартуємо, а якщо вже стартували, відновлюємо.
  4. Реклами не видно. Ставимо на паузу й вимикаємо звук.
  5. Гравець пограв, показано фінальний екран із CTA. Тап на CTA викликає mraid.open.

Код: ready і viewableChange

Цей блок адаптовано з прикладу в доках 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().

startPlayable і pausePlayable

Це наша реалізація, у доках 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-перемикачем і з блокуванням екрана.

mraid.open лише по тапу на CTA

Правило 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();
});

Перевірка: збірка без MRAID запускається в десктопному браузері

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.
  • Які версії SDK та вебвʼю вбудовують MRAID.
  • Кодеків, частоти кадрів і тривалості аудіо й відео.
  • Як саме модерація тестує playable.

У DarkCore Ramet є Playable Builder.

У DarkCore Ramet

Каркас готовий, далі потрібен масовий залив

DarkCore Ramet запускає кампанії в Unity Ads пачками: оберіть апки та гео, подивіться превʼю, а черга відправить їх у темпі, який дозволяє Unity.

Усі статті