Unity Android真机上Admob插屏广告OnAdFullScreenContentClosed未触发
我的Unity应用中,点击按钮会展示插屏广告,预期关闭广告后自动切换场景。这个功能在模拟器上运行正常,但在Android真机上,OnAdFullScreenContentClosed事件完全没被调用——广告能正常显示和关闭,但关闭后场景无法切换。以下是我的实现代码:
using UnityEngine; // 注意:确保已导入SceneManagement命名空间 using UnityEngine.SceneManagement; using GoogleMobileAds.Api; public class Mymanager : MonoBehaviour { bool isloaded = false; private InterstitialAd _interstitialAd; string sceneN = "Scene0"; #if UNITY_ANDROID private string _adUnitId = "ca-app-pub-XXXXXXXXXX"; #elif UNITY_IPHONE private string _adUnitId = "ca-app-pub-XXXXXXXXXX"; #else private string _adUnitId = "unused"; #endif void Start() { MobileAds.Initialize(initStatus => { }); LoadInterstitialAd(); } public void onClickButton() { if(isloaded){ ShowInterstitialAd(); } else { SceneManager.LoadScene(sceneN); } } public void LoadInterstitialAd() { if (_interstitialAd != null) { _interstitialAd.Destroy(); _interstitialAd = null; } var adRequest = new AdRequest(); InterstitialAd.Load(_adUnitId, adRequest, (InterstitialAd ad, LoadAdError error) => { if (error != null || ad == null) { Debug.LogError("interstitial ad failed to load an ad " + "with error : " + error); isloaded = false; return; } else { isloaded = true; } Debug.Log("Interstitial ad loaded with response : " + ad.GetResponseInfo()); _interstitialAd = ad; }); RegisterEventHandlers(_interstitialAd); } public void ShowInterstitialAd() { if (_interstitialAd != null && _interstitialAd.CanShowAd()) { _interstitialAd.Show(); } else { Debug.LogError("Interstitial ad is not ready yet."); SceneManager.LoadScene(sceneN); } } private void RegisterEventHandlers(InterstitialAd interstitialAd) { interstitialAd.OnAdPaid += (AdValue adValue) => { Debug.Log(String.Format("Interstitial ad paid {0} {1}.", adValue.Value, adValue.CurrencyCode)); }; interstitialAd.OnAdImpressionRecorded += () => { Debug.Log("Interstitial ad recorded an impression."); }; interstitialAd.OnAdClicked += () => { Debug.Log("Ad: Clicked"); }; interstitialAd.OnAdFullScreenContentOpened += () => { Debug.Log("Ad: Opend"); }; interstitialAd.OnAdFullScreenContentClosed += () => { Debug.Log("Ad: Closed"); SceneManager.LoadScene(sceneN); }; interstitialAd.OnAdFullScreenContentFailed += (AdError error) => { Debug.LogError("Ad: Failed" + "with error : " + error); SceneManager.LoadScene(sceneN); }; } }
你的代码核心问题是事件注册时机错误:RegisterEventHandlers(_interstitialAd)在InterstitialAd.Load异步调用后立即执行,但此时_interstitialAd还未被赋值(Load是异步操作,只有回调函数触发时才会初始化广告实例)。这导致你实际上没有给加载完成的插屏广告绑定任何事件处理器,所以真机上广告关闭后OnAdFullScreenContentClosed自然不会触发。
模拟器能正常运行属于偶然情况——模拟器的异步回调执行时机可能更快,刚好在RegisterEventHandlers调用前完成了_interstitialAd的赋值,但这种行为在真机上不可靠。
1. 调整事件注册时机
把RegisterEventHandlers的调用移到InterstitialAd.Load的回调函数内部,确保只在广告加载成功、实例有效时才绑定事件:
public void LoadInterstitialAd() { if (_interstitialAd != null) { _interstitialAd.Destroy(); _interstitialAd = null; } var adRequest = new AdRequest(); InterstitialAd.Load(_adUnitId, adRequest, (InterstitialAd ad, LoadAdError error) => { if (error != null || ad == null) { Debug.LogError("插屏广告加载失败,错误信息:" + error); isloaded = false; return; } else { isloaded = true; } Debug.Log("插屏广告加载成功,响应信息:" + ad.GetResponseInfo()); _interstitialAd = ad; // 移到此处,给有效广告实例注册事件 RegisterEventHandlers(_interstitialAd); }); // 移除原来此处的RegisterEventHandlers调用 }
2. 优化广告生命周期管理
在广告关闭或展示失败后,销毁广告实例并重置状态,避免重复使用失效实例:
interstitialAd.OnAdFullScreenContentClosed += () => { Debug.Log("广告已关闭"); // 销毁广告实例 interstitialAd.Destroy(); _interstitialAd = null; isloaded = false; SceneManager.LoadScene(sceneN); }; interstitialAd.OnAdFullScreenContentFailed += (AdError error) => { Debug.LogError("广告全屏展示失败,错误信息:" + error); // 销毁广告实例 interstitialAd.Destroy(); _interstitialAd = null; isloaded = false; SceneManager.LoadScene(sceneN); };
3. 确认命名空间导入
确保代码顶部已导入场景管理命名空间,否则SceneManager会报错:
using UnityEngine.SceneManagement;
修复后,广告加载成功后才会绑定事件处理器,真机上关闭广告时OnAdFullScreenContentClosed会正常触发,进而执行场景切换逻辑。
内容的提问来源于stack exchange,提问作者wonmoment

