Unity中重载场景后Google Admob激励视频回调多次触发问题
解决Unity中Admob激励视频回调多次触发的问题
你的判断完全正确——场景切换时旧的回调没有被移除,导致每次加载场景都会新增一份回调绑定,最终触发次数随场景加载次数累积。下面是最可靠的解决方案:
核心思路
每次场景卸载或Admob管理对象销毁时,主动移除所有已注册的回调;同时确保整个游戏中只有一个Admob激励视频的管理实例,从根源避免重复绑定。
具体实现步骤
1. 使用单例模式管理Admob(推荐)
创建一个全局的Admob激励视频管理类,用单例+DontDestroyOnLoad确保跨场景只有一个实例,避免重复创建对象和绑定回调。
2. 在生命周期中注册/注销回调
利用Unity的OnEnable/OnDisable(或OnDestroy)方法,在对象启用时注册回调,禁用/销毁时移除所有回调,确保每次绑定都是干净的。
完整代码示例
using UnityEngine; using System; using GoogleMobileAds.Api; public class AdmobRewardManager : MonoBehaviour { // 全局单例实例 public static AdmobRewardManager Instance { get; private set; } private RewardBasedVideoAd _rewardVideoAd; private void Awake() { // 确保唯一实例 if (Instance != null && Instance != this) { Destroy(gameObject); return; } Instance = this; DontDestroyOnLoad(gameObject); // 跨场景保留,避免重复创建 // 初始化Admob激励视频实例 _rewardVideoAd = RewardBasedVideoAd.Instance; } private void OnEnable() { // 启用时注册回调(先注销再注册,防止重复绑定) RegisterAdCallbacks(); } private void OnDisable() { // 禁用时移除所有回调,避免累积 UnregisterAdCallbacks(); } private void RegisterAdCallbacks() { // 先移除旧回调,再绑定新的 UnregisterAdCallbacks(); _rewardVideoAd.OnAdLoaded += HandleAdLoaded; _rewardVideoAd.OnAdFailedToLoad += HandleAdFailedToLoad; _rewardVideoAd.OnAdOpening += HandleAdOpened; _rewardVideoAd.OnAdStarted += HandleAdStarted; _rewardVideoAd.OnAdRewarded += HandleAdRewarded; // 建议也加上OnAdClosed等其他必要回调的注册/注销 } private void UnregisterAdCallbacks() { // 移除所有已绑定的回调 _rewardVideoAd.OnAdLoaded -= HandleAdLoaded; _rewardVideoAd.OnAdFailedToLoad -= HandleAdFailedToLoad; _rewardVideoAd.OnAdOpening -= HandleAdOpened; _rewardVideoAd.OnAdStarted -= HandleAdStarted; _rewardVideoAd.OnAdRewarded -= HandleAdRewarded; } // 回调实现逻辑 private void HandleAdLoaded(object sender, EventArgs args) { Debug.Log("激励视频加载完成"); } private void HandleAdFailedToLoad(object sender, AdFailedToLoadEventArgs args) { Debug.Log($"激励视频加载失败: {args.Message}"); } private void HandleAdOpened(object sender, EventArgs args) { Debug.Log("激励视频已打开"); } private void HandleAdStarted(object sender, EventArgs args) { Debug.Log("激励视频开始播放"); } private void HandleAdRewarded(object sender, Reward args) { Debug.Log($"用户获得奖励: {args.Type} x {args.Amount}"); // 在这里处理你的奖励发放逻辑 } // 对外公开的加载广告方法 public void LoadRewardAd(string adUnitId) { var adRequest = new AdRequest.Builder().Build(); _rewardVideoAd.LoadAd(adRequest, adUnitId); } // 对外公开的展示广告方法 public void ShowRewardAd() { if (_rewardVideoAd.IsLoaded()) { _rewardVideoAd.Show(); } else { Debug.LogError("激励视频未加载完成,无法展示"); } } }
关键细节说明
- 单例+DontDestroyOnLoad:确保Admob管理对象不会随场景切换被销毁,避免每次场景加载都重新创建实例并绑定回调。
- 先注销再注册:在
RegisterAdCallbacks中先执行注销操作,即使因为意外情况重复调用注册,也不会绑定多个相同的回调。 - 生命周期中处理回调:
OnDisable会在对象被禁用或场景卸载时触发,此时移除所有回调,确保旧实例的回调不会继续触发。
如果你不想使用单例,也可以在场景的管理脚本中,在OnDestroy方法中手动注销当前场景中绑定的Admob回调,但单例模式是更稳定、更易维护的方案。
内容的提问来源于stack exchange,提问作者mazend
相关产品推荐
相关产品推荐

