You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:20:29