Использование admob rewarded ad в едином шаблоне singleton - PullRequest
0 голосов
/ 11 июля 2020

Я использую рекламу admob в своем приложении, и они работают нормально. Но когда я пытаюсь что-то сделать после закрытия объявления или получения вознаграждения, перезвоните, мой код ломается. Ниже приведен мой скрипт adMob

public class AdMobScript : MonoBehaviour
{
    ...

    public event Action OnReviveRewardEarned;
    public event Action OnReviveAdLoaded;
    public event Action OnReviveAdClosed;

    private void LoadReviveRewardedAd()
    {

        reviveRewardedAd = new RewardedAd(adReviveRewardedId);

        reviveRewardedAd.OnAdLoaded += ReviveAdLoaded;
        reviveRewardedAd.OnUserEarnedReward += ReviveEarnedReward;
        reviveRewardedAd.OnAdClosed += ReviveAdClosed;

        AdRequest request = new AdRequest.Builder().Build();
        reviveRewardedAd.LoadAd(request);

    }

    private void ReviveAdClosed(object sender, EventArgs e)
    {
        LoadReviveRewardedAd();
        if (isRewardErned)
        {
            isRewardErned = false;
            OnReviveRewardEarned.Invoke();
        }
        else
            OnReviveAdClosed.Invoke();
    }

    private void ReviveEarnedReward(object sender, Reward e)
    {
        isRewardErned = true;
    }

    private void ReviveAdLoaded(object sender, EventArgs e)
    {
        //reviveButton.interactable = true;
        OnReviveAdLoaded.Invoke();
    }

    public void ShowAdToRevive()
    {
        if (reviveRewardedAd.IsLoaded())
        {
            reviveRewardedAd.Show();
        }
    }
    ...
}

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

public class AdManager : MonoBehaviour
{
   ...
   private void Start() {

        AdMobScript.instance.OnReviveAdClosed += ReviveAdClosed;
        AdMobScript.instance.OnReviveAdLoaded += ReviveAdLoaded;
        AdMobScript.instance.OnReviveRewardEarned += ReviveReward;

    }

    #region ReviveAds
    private void ReviveReward() {
        //game crash here
        backButton.gameObject.SetActive(true);
        reviveButton.gameObject.SetActive(false);
        noThanksButton.gameObject.SetActive(false);
        manager.Revive();
    }
    private void ReviveAdLoaded() {
        reviveButton.interactable = true;
    }
    private void ReviveAdClosed() {
        //game crash here
        reviveButton.interactable = false;
    }

    public void ShowAdToRevive() {
        AdMobScript.instance.ShowAdToRevive();
    }
   ...
}

После закрытия объявления или получения вознаграждения игра вылетает (в журнале ошибок указано

get_gameObject can only be called from the main thread

). Должно быть, я что-то делаю не так. Кто-нибудь может указать мне правильное направление?

1 Ответ

1 голос
/ 12 июля 2020

Причина проблемы - вы пытаетесь манипулировать с помощью MonoBehaviors, а не в основном потоке.

Просто напишите простой планировщик, который вызывает события в потоке Unity, например:

Scheduler :

using System;
using UnityEngine;

public class Scheduler : MonoBehaviour
{
    public static Scheduler instance;

    public event Action secondTick = delegate { };

    private float seconds = 0;

    private void Awake()
    {
        instance = this;
    }

    private void Update()
    {
        seconds += Time.unscaledDeltaTime;

        if (seconds >= 1.0f)
        {
            seconds -= 1.0f;

            secondTick.Invoke();
        }
    }
}

Обновлен сценарий AdMobScript:

public class AdMobScript : MonoBehaviour
{
    ...

    private bool onRewardEarnedCall = false;
    private bool onRewardAdLoaded = false;
    private bool onRewardAdClosed = false;
    
    public event Action OnReviveRewardEarned;
    public event Action OnReviveAdLoaded;
    public event Action OnReviveAdClosed;

    private void LoadReviveRewardedAd()
    {

        reviveRewardedAd = new RewardedAd(adReviveRewardedId);

        reviveRewardedAd.OnAdLoaded += ReviveAdLoaded;
        reviveRewardedAd.OnUserEarnedReward += ReviveEarnedReward;
        reviveRewardedAd.OnAdClosed += ReviveAdClosed;

        AdRequest request = new AdRequest.Builder().Build();
        reviveRewardedAd.LoadAd(request);


        Scheduler.instance.secondTick += OnSecondTick;
    }

    private void OnSecondTick()
    {
        if(onRewardAdClosed)
        {
            onRewardAdClosed = false;

            OnReviveAdClosed.Invoke();
        }
        
        if(onRewardEarnedCall)
        {
            OnReviveRewardEarned.Invoke();
            onRewardEarnedCall = false;
        }
        
        if(onRewardAdLoaded)
        {
            OnReviveAdLoaded.Invoke();
            onRewardAdLoaded = false;
        }
    }
    
    private void ReviveAdClosed(object sender, EventArgs e)
    {
        LoadReviveRewardedAd();
        if (isRewardErned)
        {
            isRewardErned = false;
            onRewardEarnedCall = true;
        }
        else
            onRewardAdClosed = true;
    }

    private void ReviveEarnedReward(object sender, Reward e)
    {
        isRewardErned = true;
    }

    private void ReviveAdLoaded(object sender, EventArgs e)
    {
        //reviveButton.interactable = true;
        onRewardAdLoaded = true;
    }

    public void ShowAdToRevive()
    {
        if (reviveRewardedAd.IsLoaded())
        {
            reviveRewardedAd.Show();
        }
    }
    ...
}

Это очень простое и неоптимизирующее решение, но оно решит вашу проблему.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...