显示插页式广告和奖励广告后游戏崩溃

Game crashes after showing intersitial and rewarded ads

我正在使用 admob 投放广告。广告在编辑器上运行良好,但在 phone 上则不然。我在游戏中有一个按钮可以显示激励广告,然后加载下一关。我在关卡末尾展示插页式广告,然后加载下一个关卡。但是在加载下一级游戏崩溃后。我试图修复它几天,但它一直在发生。我正在添加我的广告管理器脚本。 (单位 ID 当然不是空的)

using System.Collections;
 using UnityEngine;
 using GoogleMobileAds.Api;
 using System;
  
 public class AdManager : MonoBehaviour
 {
     public static AdManager instance;
     private BannerView bannerView;
     private RewardedAd rewardedAd;
     private InterstitialAd interstitialAd;
  
      #if UNITY_ANDROID
         string bannerAdUnitId = " ";
        
         string rewardedAdUnitId = " ";
  
         string interstitialAdUnitId = " ";
  
     #else
         string bannerAdUnitId = "unexpected_platform";
  
         string rewardedAdUnitId = "unexpected_platform";
  
         string interstitialAdUnitId = "unexpected_platform";
  
     #endif
  
     void Awake()
     {
         if(instance != null && instance != this){
             Destroy(this.gameObject);
         }
         else{
             instance = this;
             DontDestroyOnLoad(this.gameObject);
         }
     }
  
     private void Start() {
         MobileAds.Initialize(initStatus => { });
         RequestInterstitialAd();
         RequestBannerAd();
         RequestRewardedAd();
     }
  
     //BANNER
     public void RequestBannerAd(){
         if (bannerView != null)
             bannerView.Destroy();
        
         else{
             bannerView = new BannerView(bannerAdUnitId, AdSize.Banner, AdPosition.Bottom);
  
             AdRequest request = new AdRequest.Builder().Build();
  
             bannerView.LoadAd(request);
         }
     }
  
     //REWARDED
  
     public void RequestRewardedAd(){
         if(rewardedAd != null)
             rewardedAd.Destroy();
  
         rewardedAd = new RewardedAd(rewardedAdUnitId);
  
         // Called when an ad request failed to show.
         rewardedAd.OnAdFailedToShow += HandleRewardedAdFailedToShow;
         // Called when the ad is closed.
         rewardedAd.OnAdClosed += HandleRewardedAdClosed;
  
         AdRequest request = new AdRequest.Builder().Build();
  
         rewardedAd.LoadAd(request);
  
     }
  
     public void ShowRewardedAd(){
         if (rewardedAd.IsLoaded()) {
             rewardedAd.Show();
         }
         else{
             StartCoroutine(RewardedNotLoadedFunctionCall());
         }
     }
  
     IEnumerator RewardedNotLoadedFunctionCall(){
         FindObjectOfType<GameManagement>().RewardedAdNotLoaded();
         yield return null;
     }
  
     public void HandleRewardedAdClosed(object sender, EventArgs args)
     {
         RequestRewardedAd();
         StartCoroutine(AdClosedFunctionCall());
     }
     IEnumerator AdClosedFunctionCall(){
         FindObjectOfType<GameManagement>().AdClosed();
         yield return null;
     }
  
     public void HandleRewardedAdFailedToShow(object sender, AdErrorEventArgs args)
     {
         StartCoroutine(RewardedNotLoadedFunctionCall());
     }
  
     //interstitial
  
     private void RequestInterstitialAd(){
         if(interstitialAd != null)
             interstitialAd.Destroy();
  
         interstitialAd = new InterstitialAd(interstitialAdUnitId);
  
         interstitialAd.OnAdClosed += HandleOnAdClosed;
  
         AdRequest request = new AdRequest.Builder().Build();
         interstitialAd.LoadAd(request);
     }
  
     public void ShowInterstitialAd(){
         if (interstitialAd.IsLoaded()) {
             interstitialAd.Show();
         }
         else{
             StartCoroutine(AdClosedFunctionCall());
         }
     }
  
     public void HandleOnAdClosed(object sender, EventArgs args)
     {
         RequestInterstitialAd();
         StartCoroutine(AdClosedFunctionCall());
     }
 }

logcat

Admob Ad 不 运行 与 Unity 的主线程在同一线程上。

rewardedAd.OnAdClosed += HandleRewardedAdClosed;

从Admob的线程调用Unity的函数会出现意外错误。

首先,将 UnityMainThreadDispatcher 添加到您的项目中。 Admob回调调用的所有函数都需要UnityMainThreadDispatcher排队到主线程:

public void HandleRewardedAdClosed(object sender, EventArgs args)
     {
        UnityMainThreadDispatcher.Instance().Enqueue(()=>{
            RequestRewardedAd();
            StartCoroutine(AdClosedFunctionCall());
        });
     }

其次,您不应该使用 FindObjectOfType()。这是一项昂贵的操作,如果找不到 GameManagement 对象,您可能 运行 进入 NullReferenceException。由于此异常并未发生在 Unity 的主线程上,因此 logcat 消息很含糊。

您应该改用单例模式或观察者模式。

第三,即使用户跳过奖励广告,您也给予了奖励。使用 rewardedAd.OnUserEarnedReward 确保用户已获得奖励广告。