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

Unity集成AdMob遇高请求低展示问题求助(插屏/激励广告)

AdMob广告集成问题排查(Bubble Shooter Infinity)

我在Unity开发的游戏《Bubble Shooter Infinity》中集成了AdMob激励广告,虽然应用状态显示"Ready",但印度、美国、巴西等多个地区出现了高请求、低展示的异常情况。以巴西地区2025/07/01的数据为例:

  • 请求量:307
  • 展示量:16
  • 匹配率:100.00%
  • eCPM:US$4.77
  • 收益:US$0.08

已排查项

  • 应用已通过AdMob审核,状态为Ready
  • 仅使用激励广告(Rewarded Ads)和插屏广告(Interstitial Ads)两种格式
  • 各地区匹配率普遍较高(约98%)
  • 请求量持续增长,但展示量始终处于低位
  • eCPM数值偏低
  • 采用Unity + GoogleMobileAds插件的标准集成方式

问题咨询

  1. 为何匹配率良好的情况下,还会出现高请求低展示?
  2. 问题是否出在AdMob填充率、广告可用性或投放时机上?
  3. 是否需要添加插屏或横幅广告来提升填充率?
  4. 是否需要积累更多流量,才能提升美国、埃及等地区的填充率?

广告触发逻辑

  • 插屏广告:玩家每完成2关后展示
  • 激励广告:玩家分数翻倍时展示

测试环境中能正常看到广告,但正式上线后出现上述问题。

相关代码

AdsManager.cs

using System;
using System.Collections.Generic;
using BubbleShooterGameToolkit.Scripts.Ads.AdUnits;
using BubbleShooterGameToolkit.Scripts.CommonUI.Popups;
using BubbleShooterGameToolkit.Scripts.Services;
using BubbleShooterGameToolkit.Scripts.Settings;
using BubbleShooterGameToolkit.Scripts.System;
using UnityEngine;

namespace BubbleShooterGameToolkit.Scripts.Gameplay.Managers
{
    public class AdsManager : SingletonBehaviour<AdsManager>
    {
        [SerializeField] private List<AdSetting> adList = new();
        [SerializeField] private List<AdUnit> adUnits = new();
        private EPlatforms platforms;

        public override void Awake()
        {
            base.Awake();
            platforms = GetPlatform();
            var adElements = Resources.Load<AdsSettings>("Settings/AdsSettings").adProfiles;
            foreach (var t in adElements)
            {
                if (t.platforms == platforms && t.enable)
                {
                    if (Application.isEditor && !t.testInEditor)
                    {
                        continue;
                    }

                    adList.Add(t);
                    foreach (var adElement in t.adElements)
                    {
                        var adUnit = new AdUnit { PlacementId = adElement.placementId, AdReference = adElement.adReference, AdsHandler = t.adsHandler };
                        adUnit.OnInitialized = placementId => adUnit.Load();
                        adUnits.Add(adUnit);
                    }

                    t.adsHandler.Init(t.appId, false, new AdsListener(adUnits));
                }
            }
        }

        private void OnEnable()
        {
            Popup.OnOpenPopup += OnOpenPopup;
            Popup.OnClosePopup += OnClosePopup;
        }

        private void OnDisable()
        {
            Popup.OnOpenPopup -= OnOpenPopup;
            Popup.OnClosePopup -= OnClosePopup;
        }

        private EPlatforms GetPlatform()
        {
#if UNITY_ANDROID
            return EPlatforms.Android;
#elif UNITY_IOS
            return EPlatforms.IOS;
#elif UNITY_WEBGL
            return EPlatforms.WebGL;
#else
            return EPlatforms.Windows;
#endif
        }

        private void OnOpenPopup(Popup popup)
        {
            OnPopupTrigger(popup, true);
        }

        private void OnClosePopup(Popup popup)
        {
            OnPopupTrigger(popup, false);
        }

        private void OnPopupTrigger(Popup popup, bool open)
        {
            foreach (var ad in adList)
            {
                foreach (var adElement in ad.adElements)
                {

                    var adUnit = adUnits.Find(i => i.AdReference == adElement.adReference);
                    if (!adUnit.IsAvailable())
                    {
                        adUnit.Load();
                        continue;
                    }

                    if (((open && adElement.popup.showOnOpen) || (!open && adElement.popup.showOnClose)) && popup.GetType() == adElement.popup.popup.GetType())
                    {
                        if (LevelManager.instance.CurrentLevel % 2 == 0)
                        {
                            adUnit.Load();
                            adUnit.Show();
                            Debug.Log("IS ads loded" + adUnit.Loaded);
                            return;
                        }
                    }
                }
            }
        }

        public void ShowAdByType(AdReference adRef, Action<string> shown)
        {

            if (NoAdsManager.IsNoAdsPurchased)
            {
                shown?.Invoke(string.Empty);
                return;
            }

            foreach (var adUnit in adUnits)
            {
                if (adUnit.AdReference == adRef && adUnit.IsAvailable())
                {
                    adUnit.OnShown = shown;
                    adUnit.Load();
                    adUnit.Show();
                    return;
                }
            }
        }

        public bool IsRewardedAvailable(AdReference adRef)
        {
            Debug.LogError("add Check Was Called");
            foreach (var adUnit in adUnits)
            {
                Debug.LogError("check count");
               
                if (adUnit.AdReference == adRef)
                {
                    Debug.LogError("was in check");
                    if (NoAdsManager.IsNoAdsPurchased)
                    {
                        return false;
                    }
                    if (adUnit.IsAvailable())
                    {
                        Debug.LogError("is Add unit avalable " + adUnit.AdsHandler.name + " " + adUnit.IsAvailable());
                        return adUnit.IsAvailable();
                    }
                }
            }

            return false;
        }
    }
}

AdmobHandler.cs

using BubbleShooterGameToolkit.Scripts.Ads.AdUnits;
using UnityEngine;
#if ADMOB
using GoogleMobileAds.Api;
#endif

namespace BubbleShooterGameToolkit.Scripts.Ads.Networks
{
    [CreateAssetMenu(fileName = "AdmobHandler", menuName = "BubbleShooterGameToolkit/Ads/AdmobHandler")]
    public class AdmobHandler : AdsHandlerBase
    {
        private IAdsListener _listener;
        #if ADMOB
        private InterstitialAd _interstitialAd;
        private RewardedAd _rewardedAd;
        #endif

        public override void Init(string _id, bool adSettingTestMode, IAdsListener listener)
        {
            #if ADMOB
            _listener = listener;
            MobileAds.RaiseAdEventsOnUnityMainThread = true;

            MobileAds.Initialize(initstatus =>
            {
                if (initstatus == null)
                {
                    Debug.LogError("Google Mobile Ads initialization failed.");
                    return;
                }

                // If you use mediation, you can check the status of each adapter.
                var adapterStatusMap = initstatus.getAdapterStatusMap();
                if (adapterStatusMap != null)
                {
                    foreach (var item in adapterStatusMap)
                    {
                        Debug.Log(string.Format("Adapter {0} is {1}",
                            item.Key,
                            item.Value.InitializationState));
                    }
                }

                Debug.Log("Google Mobile Ads initialization complete.");
                _listener?.OnAdsInitialized();
            });
            #endif
        }

        public override void Show(AdUnit adUnit)
        {
            #if ADMOB
            _listener?.Show(adUnit);

            if (adUnit.AdReference.adType == EAdType.Interstitial)
            {
                if (_interstitialAd != null && _interstitialAd.CanShowAd())
                {
                    Debug.Log("Showing interstitial ad.");
                    _interstitialAd.Show();
                }
                else
                {
                    Debug.LogError("Interstitial ad is not ready yet.");
                }
            }
            else if (adUnit.AdReference.adType == EAdType.Rewarded)
            {
                if (_rewardedAd != null && _rewardedAd.CanShowAd())
                {
                    _rewardedAd.Show(reward =>
                    {
                        Debug.Log(string.Format("Rewarded ad granted a reward: {0} {1}",
                            reward.Amount,
                            reward.Type));
                    });
                }
                else
                {
                    Debug.LogError("Rewarded ad is not ready yet.");
                }
            }
            #endif
        }

        public override void Load(AdUnit adUnit)
        {
            #if ADMOB
            var adRequest = new AdRequest();

            if (adUnit.AdReference.adType == EAdType.Interstitial)
            {
                InterstitialAd.Load(adUnit.PlacementId, adRequest, (ad, error) =>
                {
                    if (error != null)
                    {
                        Debug.LogError("Interstitial ad failed to load an ad with error : " + error);
                        _listener.OnAdsLoadFailed();
                        return;
                    }

                    if (ad == null)
                    {
                        Debug.LogError("Unexpected error: Interstitial load event fired with null ad and null error.");
                        _listener.OnAdsLoadFailed();
                        return;
                    }

                    _interstitialAd = ad;
                    Debug.Log("Interstitial ad loaded with response : " + ad.GetResponseInfo());

                    ad.OnAdFullScreenContentClosed += () =>
                    {
                        _listener.OnAdsShowComplete();
                        _interstitialAd = null;
                        Load(adUnit);
                    };
                    ad.OnAdFullScreenContentFailed += (AdError error) =>
                    {
                        Debug.LogError("Interstitial ad failed to show: " + error);
                        _listener.OnAdsShowFailed();
                        _interstitialAd = null;
                        Load(adUnit);
                    };
                    _listener?.OnAdsLoaded(adUnit.PlacementId);
                });
            }
            else if (adUnit.AdReference.adType == EAdType.Rewarded)
            {
                RewardedAd.Load(adUnit.PlacementId, adRequest, (ad, error) =>
                {
                    if (error != null)
                    {
                        Debug.LogError("Rewarded ad failed to load an ad with error : " + error);
                        _listener.OnAdsLoadFailed();
                        return;
                    }

                    if (ad == null)
                    {
                        Debug.LogError("Unexpected error: Rewarded load event fired with null ad and null error.");
                        _listener.OnAdsLoadFailed();
                        return;
                    }

                    _rewardedAd = ad;

                    ad.OnAdFullScreenContentClosed += () =>
                    {
                        _listener.OnAdsShowComplete();
                        _rewardedAd = null;
                        Load(adUnit);
                    };
                    ad.OnAdFullScreenContentFailed += (AdError error) =>
                    {
                        Debug.LogError("Rewarded ad failed to show: " + error);
                        _listener.OnAdsShowFailed();
                        _rewardedAd = null;
                        Load(adUnit);
                    };

                    Debug.Log("Rewarded ad loaded with response : " + ad.GetResponseInfo());
                    _listener?.OnAdsLoaded(adUnit.PlacementId);
                });
            }
            #endif
        }

        public override bool IsAvailable(AdUnit adUnit)
        {
#if ADMOB
            if (adUnit.AdReference.adType == EAdType.Interstitial)
                return _interstitialAd != null && _interstitialAd.CanShowAd();
            else if (adUnit.AdReference.adType == EAdType.Rewarded)
                return _rewardedAd != null && _rewardedAd.CanShowAd();
#endif
            return false;
        }
    }
}

注意:测试时我总能正常看到插屏和激励广告

相关截图

广告数据截图1
广告数据截图2
广告数据截图3

内容的提问来源于stack exchange,提问作者Vignesh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 18:55:54