Перейти к основному содержимому
Версия: 4.2.0

Руководство по интеграции

Полное руководство по интеграции плагина BidMachine Plus для Unity.

Плагин BidMachine Plus для Unity

BidMachine Plus предоставляет два источника спроса через один API:

ModeОписание
AdNetworkBidMachine работает как источник спроса с хедер-биддингом — самостоятельно или подключённым к сторонней медиации
MediationBidMachine сам выступает платформой медиации, проводя аукцион по вашему спросу

Одни и те же классы рекламных юнитов — BannerAd, InterstitialAd, RewardedAd — работают в обоих режимах. Активный режим выбирается при инициализации.

На этой странице описаны установка плагина, инициализация и загрузка рекламы. Доступны два пути установки: автоматический через ИИ-агенты для кодинга или ручная настройка через Unity Package Manager.

Автоматическая интеграция с ИИ-агентами для кодинга

Бандл BidMachine Plus SDK Agents поставляет переносимый навык интеграции для Claude Code, Codex и Gemini. Установите его для вашей среды выполнения:

/plugin marketplace add bidmachine/bidmachine-sdk-agents
/plugin install bidmachine-sdk-agents@bidmachine

Затем попросите вашего агента добавить BidMachine Plus как First Look перед вашей существующей медиацией — например:

Промпт
Add BidMachine Plus as a First Look in front of my existing ad mediation in this Unity game.

Встроенный навык управляет интеграцией: устанавливает плагин, инициализирует BidMachine в режиме Mediation и подключает BidMachine Plus как основной источник для interstitial и rewarded — запрашивается первым по таймауту — с фолбэком на вашу существующую медиацию (MAX, AdMob, LevelPlay или другую) при отсутствии заполнения, сохраняя текущую настройку.

First Look покрывает только interstitial и rewarded. Для баннеров используйте ручную настройку ниже — плагин их поддерживает, но в поток First Look они не входят.

Ручная установка

Требуется Unity 2021.3+, Android SDK 23+, iOS 13.0+ и Xcode 16.4+.

Unity Package Manager

BidMachine Plus распространяется через scoped-реестр BidMachine. Зарегистрируйте его, затем установите com.bidmachine.plus. External Dependency Manager подтягивается автоматически как зависимость пакета — отдельный импорт не нужен.

  1. Откройте Edit → Project Settings → Package Manager.
  2. В разделе Scoped Registries нажмите + и заполните:
    • Name: BidMachine Registry
    • URL: https://npm.bidmachine.com
    • Scope(s): com.bidmachine
  3. Нажмите Apply.
  4. Откройте Window → Package Manager, переключите источник на My Registries, выберите BidMachine Plus и нажмите Install.

Настройка Android

В Player Settings → Publishing Settings включите Custom Main Gradle Template и Custom Gradle Settings Template.

В Assets → External Dependency Manager → Android Resolver → Settings включите Patch mainTemplate.gradle, Copy and patch settingsTemplate.gradle from 2022.2 и Use Jetifier. Затем запустите Android Resolver → Resolve.

Обязательные разрешения в AndroidManifest.xml:

Plugins/Android/AndroidManifest.xml
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />

Необязательные разрешения:

Plugins/Android/AndroidManifest.xml
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.VIBRATE" />

Настройка iOS

В Assets → External Dependency Manager → iOS Resolver → Settings отключите Link frameworks statically.

Добавьте в Info.plist экспортированного проекта Xcode:

Info.plist
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>

<key>SKAdNetworkItems</key>
<array>
<!-- full SKAdNetwork list is published with the SDK -->
</array>

<key>NSUserTrackingUsageDescription</key>
<string>$(APP_NAME) needs your advertising identifier to deliver personalized ads.</string>

Инициализация

Вызовите BidMachine.Initialize один раз при запуске приложения. Передайте нужный режим, чтобы выбрать источник спроса.

BidMachine.GetInstance возвращает экземпляр SDK — сохраните ссылку на него; вы будете передавать его в конструктор каждого рекламного юнита.

BidMachine Plus инициализируется в одном из двух режимов, выбираемых параметром IntegrationMode, который вы передаёте билдеру:

Режим AdNetwork

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

var sdk = BidMachine.GetInstance("YOUR_APP_KEY");

var config = new InitializationConfigBuilder(IntegrationMode.AdNetwork)
.WithMediator(MediationProvider.AdMob) // the mediation BidMachine plugs into — or MediationProvider.LevelPlay, MediationProvider.Max, a custom string
.WithLoggingEnabled(true) // remove before release
.WithTestModeEnabled(true) // remove before release
.Build();

sdk.Initialized += (sender, args) =>
{
if (args.Error != null) Debug.LogError($"init failed: {args.Error.Message}");
};
sdk.Initialize(config);

Режим Mediation

BidMachine сам выступает платформой медиации, проводя аукцион по вашему спросу. Передайте IntegrationMode.Mediation — сторонний медиатор объявлять не нужно:

var config = new InitializationConfigBuilder(IntegrationMode.Mediation)
.WithLoggingEnabled(true) // remove before release
.WithTestModeEnabled(true) // remove before release
.Build();

var sdk = BidMachine.GetInstance("YOUR_APP_KEY");
sdk.Initialized += (sender, args) => { /* ready */ };
sdk.Initialize(config);

В обоих режимах классы рекламных юнитов предоставляют NotifyWin() и NotifyLoss(winnerEcpm, networkName) для сообщения о результате раунда вотерфолла — см. Медиация.

Проводите аукцион на собственном сервере? См. S2S-биддинг для описания потока bid-токена и загрузки с bidPayload.

Интеграция рекламы

Все события жизненного цикла рекламы доставляют объект AdInfo, описывающий победившую рекламу (через EventArgs.AdInfo):

PropertyTypeОписание
PlacementIdstringID плейсмента из панели BidMachine
PricedoubleeCPM ÷ 1000 (например, 0.005 = $5 CPM)
PrecisionRevenuePrecisionОдно из Estimated, Exact, Unknown
RawDataIReadOnlyDictionary<string, string>Метаданные сети. Известные ключи: networkName, dsp, ecpm

Читайте победившую сеть через e.AdInfo.RawData["networkName"], а доход по конкретному показу — через e.AdInfo.Price.

e.AdInfo.Precision описывает, насколько надёжна эта цена:

ValueЗначение
ExactЦена аукциона в реальном времени — можно доверять для отчётности
EstimatedОценка по историческим данным — считайте приблизительной
UnknownДостоверность определить невозможно

Все события рекламы срабатывают в основном потоке Unity, поэтому из них можно напрямую обновлять UI и вызывать API MonoBehaviour.

Реклама Interstitial

Полноэкранная реклама. Создайте один раз, загрузите, затем вызовите Show, когда она готова. Перезагружайте из Closed, чтобы держать рекламу готовой к следующему показу.

AdsController.cs
public class AdsController : MonoBehaviour
{
private InterstitialAd interstitialAd;

private void CreateInterstitialAd()
{
interstitialAd = new InterstitialAd(sdk, placementId: "YOUR_PLACEMENT_ID");

interstitialAd.Loaded += (s, e) => Debug.Log($"Interstitial loaded from {e.AdInfo.RawData["networkName"]}");
interstitialAd.LoadFailed += (s, e) => Debug.LogError($"Interstitial load failed: {e.Error.Message}");
interstitialAd.Shown += (s, e) => Debug.Log("Interstitial displayed");
interstitialAd.ShowFailed += (s, e) => Debug.LogError($"Interstitial show failed: {e.Error.Message}");
interstitialAd.Clicked += (s, e) => Debug.Log("Interstitial clicked");
interstitialAd.Closed += (s, e) => interstitialAd.Load(); // reload for next show
interstitialAd.Expired += (s, e) => Debug.LogWarning("Interstitial expired before show");
interstitialAd.RevenuePaid += (s, e) => Debug.Log($"Interstitial revenue: {e.AdInfo.Price} from {e.AdInfo.RawData["networkName"]}");

interstitialAd.Load();
}

private void ShowInterstitialAd()
{
if (interstitialAd.IsLoaded)
{
interstitialAd.Show();
}
else
{
Debug.LogWarning("Interstitial ad not ready yet");
}
}

private void OnDestroy()
{
interstitialAd?.Dispose();
}
}
CallbackОписание
LoadedРеклама загружена и готова к показу
LoadFailedНе удалось загрузить рекламу
ShownРеклама отображается на весь экран
ShowFailedНе удалось отобразить рекламу
ClickedПользователь нажал на рекламу
ClosedПользователь закрыл рекламу
ExpiredСрок действия рекламы истёк до показа
RevenuePaidЗафиксирован оплачиваемый показ

Реклама Rewarded

Тот же жизненный цикл, что и у interstitial, плюс колбэк UserQualifiedForReward, когда пользователь завершает просмотр рекламы и получает вознаграждение.

AdsController.cs
public class AdsController : MonoBehaviour
{
private RewardedAd rewardedAd;

private void CreateRewardedAd()
{
rewardedAd = new RewardedAd(sdk, placementId: "YOUR_PLACEMENT_ID");

rewardedAd.Loaded += (s, e) => Debug.Log($"Rewarded loaded from {e.AdInfo.RawData["networkName"]}");
rewardedAd.UserQualifiedForReward += (s, e) =>
{
Debug.Log($"Reward earned: {e.Reward?.Amount} {e.Reward?.Label}");
// grant reward to the user
};
rewardedAd.LoadFailed += (s, e) => Debug.LogError($"Rewarded load failed: {e.Error.Message}");
rewardedAd.Shown += (s, e) => { };
rewardedAd.ShowFailed += (s, e) => { };
rewardedAd.Clicked += (s, e) => { };
rewardedAd.Closed += (s, e) => rewardedAd.Load(); // reload for next show
rewardedAd.Expired += (s, e) => { };
rewardedAd.RevenuePaid += (s, e) => Debug.Log($"Rewarded revenue: {e.AdInfo.Price} from {e.AdInfo.RawData["networkName"]}");

rewardedAd.Load();
}

private void ShowRewardedAd()
{
if (rewardedAd.IsLoaded)
{
rewardedAd.Show();
}
else
{
Debug.LogWarning("Rewarded ad not ready yet");
}
}

private void OnDestroy()
{
rewardedAd?.Dispose();
}
}
CallbackОписание
LoadedРеклама загружена и готова к показу
UserQualifiedForRewardПользователь завершил просмотр, выдайте вознаграждение
LoadFailedНе удалось загрузить рекламу
ShownРеклама отображается на весь экран
ShowFailedНе удалось отобразить рекламу
ClickedПользователь нажал на рекламу
ExpiredСрок действия рекламы истёк до показа
RevenuePaidЗафиксирован оплачиваемый показ

Аргументы события UserQualifiedForReward предоставляют Reward (может быть null, если метаданные вознаграждения не заданы), которое содержит Label (string) и Amount (int).

Реклама Banner

BannerAd отображается в виде оверлея, прикреплённого к краю экрана. Загрузите его, затем вызовите Show(position) из обработчика Loaded; вызовите Hide(), чтобы убрать его. Это одноразовый показ — баннер не обновляется автоматически.

SizeРазмерыСценарий использования
BannerAdSize.Banner320 × 50Стандартный баннер
BannerAdSize.Leaderboard728 × 90Планшеты
BannerAdSize.MRec300 × 250Средний прямоугольник
BannerAdSize.Adaptive(width, maxHeight)произвольныеГибкая компоновка
подсказка

Используйте BannerAdSize.GetMaxAdaptiveHeight(width), чтобы вычислить maxHeight для адаптивных баннеров.

Вызовите Show(position) на загруженном BannerAd, чтобы прикрепить его к одной из позиций ниже. Вызовите Hide(), чтобы убрать его с экрана.

ПозицияConstant
СверхуBannerPosition.HorizontalTop
СнизуBannerPosition.HorizontalBottom
СлеваBannerPosition.VerticalLeft
СправаBannerPosition.VerticalRight
var banner = new BannerAd(sdk, placementId: "YOUR_PLACEMENT_ID", size: BannerAdSize.Banner);

banner.Loaded += (s, e) => banner.Show(BannerPosition.HorizontalBottom); // default position
banner.LoadFailed += (s, e) => Debug.LogError($"Banner load failed: {e.Error.Message}");
banner.Shown += (s, e) => { };
banner.ShowFailed += (s, e) => { };
banner.Clicked += (s, e) => { };
banner.Expired += (s, e) => { };
banner.RevenuePaid += (s, e) => { };

banner.Load();

// Later:
banner.Hide(); // remove the overlay; Show(position) can re-display it
banner.Dispose();
EventОписание
LoadedРеклама загружена и готова к показу
LoadFailedНе удалось загрузить рекламу
ShownБаннер виден на экране, показ зафиксирован
ShowFailedНе удалось отобразить рекламу
ClickedПользователь нажал на рекламу
ExpiredСрок действия рекламы истёк до показа
RevenuePaidЗафиксирован оплачиваемый показ

Дополнительные данные паблишера

Прикрепляйте произвольные пары ключ → значение, передаваемые с bid-запросом как дополнительные данные паблишера. API существует на двух уровнях с одинаковой формой — выбирайте тот, что соответствует нужной области применения.

ОбластьГде вызыватьПрименяется к
Для всего SDKBidMachine.AddExtraКаждый аукцион этого экземпляра
Для рекламного юнита<AdUnit>.AddExtraТолько аукционы этого плейсмента

Передача null в качестве значения удаляет ключ. Дополнительные данные на уровне рекламного юнита переопределяют значения уровня SDK для того же ключа в этом плейсменте.

Для всего SDK

var sdk = BidMachine.GetInstance("YOUR_APP_KEY");

sdk.AddExtra("user_segment", "whale");
sdk.AddExtra("ab_bucket", "control");

IReadOnlyDictionary<string, string> all = sdk.GetExtras();
sdk.AddExtra("ab_bucket", null); // remove

Для рекламного юнита

Доступно на BannerAd, InterstitialAd и RewardedAd:

interstitialAd.AddExtra("placement_context", "level_complete");
bannerAd.AddExtra("screen", "main_menu");

IReadOnlyDictionary<string, string> extras = interstitialAd.GetExtras();