Найти в Дзене
Денис Скрягин

Яндекс реклама в Unity3D

Оглавление

Приветствую. Я увлекаюсь разработкой игр на Unity, и с последними событиями, столкнулся с проблемой что реклама в играх для русских разработчиков стала не доступна в плане получения хоть каких то шейкилей.

Я решил познакомиться с рекламой от Яндекса. Первое впечатление было не приятным, реклама не показывалась, в первую очередь для тестирования её работоспособности. Через неделю вернулся к ней, так как хотел хоть как то монетизировать игру. И спустя пару дней настроек, все заработало, а через месяц получил свои первые мани на карту, при чем всё легально и без больших потерь, всего 6% налога, но это мелочи.

В чем была трудность? В коде! Нет никаких адекватных документаций, особенно для тех кто только начал осваивать эту сферу.

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

Опустим момент регистрации на сайте Рекламной сети Яндекс (partner.yandex.ru), пройдите её самостоятельно. Реквизиты добавлять сразу не обязательно, до первой выплаты нужно еще монеток заработать.

Добавляем приложение и рекламный блок, это делается в пару кликов. Учтите, чтобы привязать приложение к магазину, пройдет неделя когда оно будет появляться в списке (на данный момент именно так).

Интеграция в проект

Скачиваем плагин последней версии с гита (https://github.com/yandexmobile/yandex-ads-unity-plugin/tree/master/mobileads-unity-plugin) у меня версия 2.1.1

Импортируем его в проект, ничего не поломает, не волнуйтесь.
Unity будет ругаться на 1 файл, находящийся в папке Editor, его можно спокойно удалить если игра под Андроид (иначе, ищите решение проблемы)

А теперь самое интересное

Создаем скрипт. Для удобства я называю его YADS, так и обращаться из когда к нему удобно и вообще...

В начале кода добавляем переменные.

public static YADS manager; 
private Action _actionAD_full_complite;
private Action _actionAD_close;
private Action _actionAD_error;

DateTime _startWatch;
public static YADS manager; private Action _actionAD_full_complite; private Action _actionAD_close; private Action _actionAD_error; DateTime _startWatch;

Они нужны для взаимодействия со всеми блоками кода без проблем.

В Awake назначаем для переменной manager сами себя (скрипт) с расчетом что в сцене этот скрипт будет использоваться в единственном экземпляре.

В Awake пишем вот это
В Awake пишем вот это

Вознаграждаемая реклама

Добавляем метод вызова загрузки вознаграждаемой рекламы.

 [SerializeField] private RewardedAd rewardedAd; //переменная с рекламой 
    public static void ShowRewardedAd(string idPlacement, Action actionComplite = null, Action actionClose = null, Action actionError = null)
    {
        manager.rewardedAd = new RewardedAd(idPlacement); //заполняем переменную с рекламой
        AdRequest request = new AdRequest.Builder().Build(); //создаём запрос на рекламу
        manager.rewardedAd.LoadAd(request); // отсылаем запрос на рекламу
                                            //начинаем отслеживать события рекламы
        manager.rewardedAd.OnRewardedAdLoaded += manager.HandleRewardedAdLoaded;
        manager.rewardedAd.OnRewardedAdFailedToLoad += manager.HandleRewardedAdFailedToLoad;
        manager.rewardedAd.OnReturnedToApplication += manager.HandleReturnedToApplication;
        manager.rewardedAd.OnLeftApplication += manager.HandleLeftApplication;
        manager.rewardedAd.OnRewardedAdShown += manager.HandleRewardedAdShown;
        manager.rewardedAd.OnRewardedAdDismissed += manager.HandleRewardedAdDismissed;
        manager.rewardedAd.OnImpression += manager.HandleImpression;
        manager.rewardedAd.OnRewarded += manager.HandleRewarded;

        manager._actionAD_full_complite = actionComplite;
        manager._actionAD_close = actionClose;
        manager._actionAD_error = actionError;
    }
[SerializeField] private RewardedAd rewardedAd; //переменная с рекламой public static void ShowRewardedAd(string idPlacement, Action actionComplite = null, Action actionClose = null, Action actionError = null) { manager.rewardedAd = new RewardedAd(idPlacement); //заполняем переменную с рекламой AdRequest request = new AdRequest.Builder().Build(); //создаём запрос на рекламу manager.rewardedAd.LoadAd(request); // отсылаем запрос на рекламу //начинаем отслеживать события рекламы manager.rewardedAd.OnRewardedAdLoaded += manager.HandleRewardedAdLoaded; manager.rewardedAd.OnRewardedAdFailedToLoad += manager.HandleRewardedAdFailedToLoad; manager.rewardedAd.OnReturnedToApplication += manager.HandleReturnedToApplication; manager.rewardedAd.OnLeftApplication += manager.HandleLeftApplication; manager.rewardedAd.OnRewardedAdShown += manager.HandleRewardedAdShown; manager.rewardedAd.OnRewardedAdDismissed += manager.HandleRewardedAdDismissed; manager.rewardedAd.OnImpression += manager.HandleImpression; manager.rewardedAd.OnRewarded += manager.HandleRewarded; manager._actionAD_full_complite = actionComplite; manager._actionAD_close = actionClose; manager._actionAD_error = actionError; }

Этот метод создает объект рекламы, назначается ID для загрузки, запускается метод её загрузки, и конечно подпись на события, для дальнейшей обработки рекламы.

Разберемся с событиями по подробнее. Для разных типов рекламы они практически одинаковые.

private void ShowRewardedAd()     {
        //если реклама загружена — показываем её
        if (this.rewardedAd.IsLoaded())
        {
            manager._startWatch = DateTime.Now;
            rewardedAd.Show();
        }
        else
        {

        }
    }

    //каждый метод будет вызван при определенном действии связанной с рекламой (её загрузкой и тд)
    public void HandleRewardedAdLoaded(object sender, EventArgs args)
    {
        ShowRewardedAd(); //реклама загружена — показываем её
    }
private void ShowRewardedAd() { //если реклама загружена — показываем её if (this.rewardedAd.IsLoaded()) { manager._startWatch = DateTime.Now; rewardedAd.Show(); } else { } } //каждый метод будет вызван при определенном действии связанной с рекламой (её загрузкой и тд) public void HandleRewardedAdLoaded(object sender, EventArgs args) { ShowRewardedAd(); //реклама загружена — показываем её }

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

Остальные события...

    public void HandleRewardedAdFailedToLoad(object sender, AdFailureEventArgs args)     {
        _actionAD_error?.Invoke();
    }
    public void HandleReturnedToApplication(object sender, EventArgs args)
    {
    }
    public void HandleLeftApplication(object sender, EventArgs args)
    {
    }
    public void HandleRewardedAdShown(object sender, EventArgs args)
    {
    }
    public void HandleRewardedAdDismissed(object sender, EventArgs args)
    {
        _actionAD_error?.Invoke();
    }
    public void HandleImpression(object sender, ImpressionData impressionData)
    {
    }
public void HandleRewardedAdFailedToLoad(object sender, AdFailureEventArgs args) { _actionAD_error?.Invoke(); } public void HandleReturnedToApplication(object sender, EventArgs args) { } public void HandleLeftApplication(object sender, EventArgs args) { } public void HandleRewardedAdShown(object sender, EventArgs args) { } public void HandleRewardedAdDismissed(object sender, EventArgs args) { _actionAD_error?.Invoke(); } public void HandleImpression(object sender, ImpressionData impressionData) { }

Так при события ошибки загрузки (HandleRewardedAdFailedToLoad) и (HandleRewardedAdDismissed) я активирую полученные из точки вызова Action содержащий код, который нужно выполнить при его вызове. Это очень удобно. С другими событиями тоже можно работать, но я и без них справляюсь.

И последнее событие Вознаграждение за просмотр.

    public void HandleRewarded(object sender, Reward args)     {
        if ((DateTime.Now - _startWatch).TotalSeconds > 5)
        {
            _actionAD_full_complite?.Invoke();
        }
        else
        {
            _actionAD_error?.Invoke();
        }

        manager._actionAD_full_complite = null;
        manager._actionAD_close = null;
        manager._actionAD_error = null;

        rewardedAd.Destroy();
    }
public void HandleRewarded(object sender, Reward args) { if ((DateTime.Now - _startWatch).TotalSeconds > 5) { _actionAD_full_complite?.Invoke(); } else { _actionAD_error?.Invoke(); } manager._actionAD_full_complite = null; manager._actionAD_close = null; manager._actionAD_error = null; rewardedAd.Destroy(); }

Я проверяю, разницу времени между началом показа рекламы и моментом срабатывания события для награды. Если прошло более 5 секунд - реклама была реально показана, и вызываю Action который дает игроку награду. Иначе, вызываем Action как при ошибке, это может значить, что реклама не показалась даже минимум времени, либо у игрока взломана прошивка (root) и он может запросто пропускать просмотр рекламы получая за это награду. После чего обнуляем события, дабы они не сработали в какой то другой момент (у меня такое было во время тестирования) и уничтожаем блок рекламы, для освобождения места в памяти.

Вызываем рекламу в коде

Вот просто код для вызова рекламы, с заполненными Action-ами

public void AdUnlockFon()     {
        YADS.ShowRewardedAd("R-M-1643746-7", () =>
        {
            ServerManager.SendMessageServer("AdUnlockFon", _nomer);
            WindowsController.Loading(true);
        },
        () =>
        {
            WindowsController.Loading(false);
        },
        () =>
        {
            WindowsController.Loading(false);
        });
    }
public void AdUnlockFon() { YADS.ShowRewardedAd("R-M-1643746-7", () => { ServerManager.SendMessageServer("AdUnlockFon", _nomer); WindowsController.Loading(true); }, () => { WindowsController.Loading(false); }, () => { WindowsController.Loading(false); }); }

В игре есть возможность разблокировать фон за просмотр рекламы. При нажатии игроком кнопки в игре "Открыть" я запускаю этот метод.

YADS - скрипт отвечающий за показ рекламы (не забываем, что он должен быть на сцене в единственном экземпляре)

YADS.ShowRewardedAd() - метод запроса показа рекламы. И что же он содержит...

"R-M-1643746-7" - номер рекламного блока, он выдается при создании его на сайте ЯРС (Яндекс - Рекламные Сети) для вашего приложения. У вас он свой.

Дальше нужно создать и заполнить Action-ны.

()=>{ код }

по такой логике.

Первый Action - при успешном показе

Второй Action - при закрытии рекламы (этот метод срабатывает когда игрок закрывает рекламу, как при успешном показе так и при прерывании просмотра). Будьте внимательны с тем что сюда писать.

Третий Action - при неудачной загрузке рекламы.

Так же заместо "()=>{ код }" можно написать "null", если вам ничего выполнять не нужно.

На этом с Вознаграждаемой рекламой закончили. Если что то не понятно или не работает, задавайте вопросы в комментариях.

Межстраничная реклама

Метод вызываемы из другого места в скриптах игры

private Interstitial interstitial; //переменная с рекламой     public static void ShowInterstitial(string idPlacement)
    {
        manager.interstitial = new Interstitial(idPlacement); 
        AdRequest request = new AdRequest.Builder().Build(); 
        manager.interstitial.LoadAd(request); 

        manager.interstitial.OnInterstitialLoaded += manager.HandleInterstitialLoaded;
        manager.interstitial.OnInterstitialFailedToLoad += manager.HandleInterstitialFailedToLoad;
        manager.interstitial.OnReturnedToApplication += manager.HandleReturnedToApplication;
        manager.interstitial.OnLeftApplication += manager.HandleLeftApplication;
        manager.interstitial.OnInterstitialShown += manager.HandleInterstitialShown;
        manager.interstitial.OnInterstitialDismissed += manager.HandleInterstitialDismissed;
        manager.interstitial.OnImpression += manager.HandleImpression;
    }
private Interstitial interstitial; //переменная с рекламой public static void ShowInterstitial(string idPlacement) { manager.interstitial = new Interstitial(idPlacement); AdRequest request = new AdRequest.Builder().Build(); manager.interstitial.LoadAd(request); manager.interstitial.OnInterstitialLoaded += manager.HandleInterstitialLoaded; manager.interstitial.OnInterstitialFailedToLoad += manager.HandleInterstitialFailedToLoad; manager.interstitial.OnReturnedToApplication += manager.HandleReturnedToApplication; manager.interstitial.OnLeftApplication += manager.HandleLeftApplication; manager.interstitial.OnInterstitialShown += manager.HandleInterstitialShown; manager.interstitial.OnInterstitialDismissed += manager.HandleInterstitialDismissed; manager.interstitial.OnImpression += manager.HandleImpression; }

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

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

 private void ShowInterstitial()     {
        if (this.interstitial.IsLoaded())
        {
            interstitial.Show();
        }
    }
    public void HandleInterstitialLoaded(object sender, EventArgs args)
    {
        ShowInterstitial(); //при загрузки рекламы — показываем её
    }
    public void HandleInterstitialFailedToLoad(object sender, AdFailureEventArgs args)
    {

    }
    public void HandleInterstitialShown(object sender, EventArgs args)
    {
        interstitial.Destroy();
    }
    public void HandleInterstitialDismissed(object sender, EventArgs args)
    {

    }
private void ShowInterstitial() { if (this.interstitial.IsLoaded()) { interstitial.Show(); } } public void HandleInterstitialLoaded(object sender, EventArgs args) { ShowInterstitial(); //при загрузки рекламы — показываем её } public void HandleInterstitialFailedToLoad(object sender, AdFailureEventArgs args) { } public void HandleInterstitialShown(object sender, EventArgs args) { interstitial.Destroy(); } public void HandleInterstitialDismissed(object sender, EventArgs args) { }

Самое главное событие, загрузки рекламы. Оно запускает метод показа.

Метод "HandleInterstitialShown" вызывается после показа рекламы, и удаляет ее из памяти телефона. Это важно!

Баннерная реклама

Переменные с метод запроса на загрузку и показ баннера.

Banner _banner = null;     private bool _activeBanner = false;
    private bool _activeBannerYADS = false;
    private string _idBannerYADS = "";
    
public static void ShowBanner(string id, AdPosition pos)
    {
        manager._idBannerYADS = id;

        AdSize bannerMaxSize = AdSize.FlexibleSize(manager.GetScreenWidthDp(), 90);

        manager._banner = new Banner(manager._idBannerYADS, bannerMaxSize, pos);

        manager._banner.OnAdLoaded += manager.Banner_HandleLoaded;
        manager._banner.OnAdFailedToLoad += manager.Banner_HandleAdFailedToLoad;
        manager._banner.OnReturnedToApplication += manager.Banner_HandleReturnedToApplication;
        manager._banner.OnLeftApplication += manager.Banner_HandleLeftApplication;
        manager._banner.OnAdClicked += manager.Banner_HandleAdClicked;
        manager._banner.OnImpression += manager.Banner_HandleImpression;

        AdRequest request = new AdRequest.Builder().Build();
        manager._banner?.LoadAd(request);
        manager._activeBanner = true;
    }

    private int GetScreenWidthDp()
    {
        int screenWidth = (int)Screen.safeArea.width;
        return ScreenUtils.ConvertPixelsToDp(screenWidth);
    }
Banner _banner = null; private bool _activeBanner = false; private bool _activeBannerYADS = false; private string _idBannerYADS = ""; public static void ShowBanner(string id, AdPosition pos) { manager._idBannerYADS = id; AdSize bannerMaxSize = AdSize.FlexibleSize(manager.GetScreenWidthDp(), 90); manager._banner = new Banner(manager._idBannerYADS, bannerMaxSize, pos); manager._banner.OnAdLoaded += manager.Banner_HandleLoaded; manager._banner.OnAdFailedToLoad += manager.Banner_HandleAdFailedToLoad; manager._banner.OnReturnedToApplication += manager.Banner_HandleReturnedToApplication; manager._banner.OnLeftApplication += manager.Banner_HandleLeftApplication; manager._banner.OnAdClicked += manager.Banner_HandleAdClicked; manager._banner.OnImpression += manager.Banner_HandleImpression; AdRequest request = new AdRequest.Builder().Build(); manager._banner?.LoadAd(request); manager._activeBanner = true; } private int GetScreenWidthDp() { int screenWidth = (int)Screen.safeArea.width; return ScreenUtils.ConvertPixelsToDp(screenWidth); }

Вам могут не понадобиться все переменные как у меня. Смотрите внимательнее как лучше всего заполнить параметры для рекламы.

Метод "ShowBanner()" принимает значение string и AdPosition, в которых мы в точке вызова будем передавать информацию с ID загружаемого блока и его положения на экране.

"bannerMaxSize" - очень удобная переменная типа AdSize. Ему присваивается значения метода AdSize.FlexibleSize() - метод задает максимальный размер рекламного блока по ширине и высоте. В него пишем "manager.GetScreenWidthDp(), 90".

Разберем подробнее. Метод "GetScreenWidthDp()" возвращает ширину экрана с учетом плотности пиксилей, для мобильных и планшетов это разные значения.

Следующий параметр (90) - максимальная высота.

Так как для мобильных устройств используется баннер размера 320 x 50 (это стандарт), а для планшетов 728 x 90.

Так при указании таких параметров, на разных устройствах вы получить рекламу нужного размера.

После чего создаем рекламный блок, указав все необходимые параметры.

Прикрепляем события.

Событие успешной загрузки баннера.

     public void Banner_HandleLoaded(object sender, EventArgs args)
    {
        _banner?.Show();
    }
public void Banner_HandleLoaded(object sender, EventArgs args) { _banner?.Show(); }

Так при загрузке баннера, сразу его показываем.

Остальные методы...

public void Banner_HandleAdFailedToLoad(object sender, AdFailureEventArgs args)     {

    }

    public void Banner_HandleLeftApplication(object sender, EventArgs args)
    {

    }

    public void Banner_HandleReturnedToApplication(object sender, EventArgs args)
    {

    }

    public void Banner_HandleAdClicked(object sender, EventArgs args)
    {

    }

    public void Banner_HandleImpression(object sender, ImpressionData impressionData)
    {
        Invoke("Banner_Update", 30);
    }
public void Banner_HandleAdFailedToLoad(object sender, AdFailureEventArgs args) { } public void Banner_HandleLeftApplication(object sender, EventArgs args) { } public void Banner_HandleReturnedToApplication(object sender, EventArgs args) { } public void Banner_HandleAdClicked(object sender, EventArgs args) { } public void Banner_HandleImpression(object sender, ImpressionData impressionData) { Invoke("Banner_Update", 30); }

Тут будет важен метод "Banner_HandleImpression" он вызывается, когда баннер был показан.

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

Яндекс считает показ успешным если он был на экране хотя бы 2 секунды, но советую обновлять рекламный блок не чаще чем раз в 10 секунд. Так и для пользователей будет приятнее, ведь есть те, кто смотрит с некой заинтересованностью.

С учетом того что Яндекс показывает таргетированную рекламу, для кого то это может быть и полезно, так что 10-20 секунды достаточно для ознакомления с ним.

Так, а вот и метод обновления баннера.

    public void Banner_Update()     {
        _banner?.Hide();

        AdRequest request = new AdRequest.Builder().Build();
        _banner?.LoadAd(request);
    }
public void Banner_Update() { _banner?.Hide(); AdRequest request = new AdRequest.Builder().Build(); _banner?.LoadAd(request); }

В этом методе, я выключаю баннер

_banner?.Hide();

И сразу делаю запрос на загрузку нового блока.

Для пользователя это выглядит как клац-клац и новая реклама.

Конец

Вот и конец статьи. Надеюсь я помог вам разобраться в основных моментах работы рекламы от Яндекса.