在统一单例模式中使用 admob 奖励广告

Using admob rewarded ad in unity singleton pattern

我在我的应用程序中使用了 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

)。一定是我做错了什么。谁能给我指出正确的方向?

问题的原因 - 您试图使用 MonoBehaviors 进行操作,而不是在主线程中。

只需编写调用 Unity 线程中的事件的简单调度程序,如下所示:

调度器:

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();
        }
    }
    ...
}

这是一个非常简单且未优化的解决方案,但这将解决您的问题。