支持可折叠banner

This commit is contained in:
juncong lee 2025-09-16 21:29:51 +08:00
parent 36df6b8967
commit e024f00451
21 changed files with 503 additions and 145 deletions

View File

@ -34,22 +34,22 @@ namespace WZ
/// <summary> /// <summary>
/// 检查横幅广告是否可用 /// 检查横幅广告是否可用
/// </summary> /// </summary>
bool IsBannerAvailable(); bool IsBannerAvailable(BannerType bannerType);
/// <summary> /// <summary>
/// 显示横幅广告 /// 显示横幅广告
/// </summary> /// </summary>
void DisplayBanner(); void DisplayBanner(BannerType bannerType,BannerAlignType bannerAlignType);
/// <summary> /// <summary>
/// 隐藏横幅广告 /// 隐藏横幅广告
/// </summary> /// </summary>
void HideBanner(); void HideBanner(BannerType bannerType);
/// <summary> /// <summary>
/// 获取横幅广告收益信息 /// 获取横幅广告收益信息
/// </summary> /// </summary>
double GetBannerRevenue(); double GetBannerRevenue(BannerType bannerType);
#endregion #endregion

View File

@ -3,6 +3,7 @@ using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using GoogleMobileAds.Api; using GoogleMobileAds.Api;
using GoogleMobileAds.Common;
using UnityEngine; using UnityEngine;
@ -14,6 +15,7 @@ namespace WZ
public string ClientName => "Admob"; public string ClientName => "Admob";
public PlatformType Platfrom => PlatformType.Admob; public PlatformType Platfrom => PlatformType.Admob;
private AdmobBannerAdManager _admobBannerAdManager; private AdmobBannerAdManager _admobBannerAdManager;
private AdmobCollapsibleBannerAdManager _admobCollapsibleBannerAdManager;
private AdmobInterstitialAdManager _admobInterstitialAdManager; private AdmobInterstitialAdManager _admobInterstitialAdManager;
private AdmobRewardedAdManager _admobRewardedAdManager; private AdmobRewardedAdManager _admobRewardedAdManager;
private AdmobNativeAdManager _admobNativeAdManager; private AdmobNativeAdManager _admobNativeAdManager;
@ -23,6 +25,7 @@ namespace WZ
private List<string> _nativeAdUnits = new List<string>(); private List<string> _nativeAdUnits = new List<string>();
private List<string> _splashAdUnits = new List<string>(); private List<string> _splashAdUnits = new List<string>();
private List<string> _bannerAdUnits = new List<string>(); private List<string> _bannerAdUnits = new List<string>();
private List<string> _collapsibleBannerAdUnits = new List<string>();
private string _rvPos; private string _rvPos;
private string _ivPos; private string _ivPos;
private string _naPos; private string _naPos;
@ -31,8 +34,6 @@ namespace WZ
private Action _rvShowFailedCallback = null; private Action _rvShowFailedCallback = null;
private float _rvStartLoadTime = 0; private float _rvStartLoadTime = 0;
private float _ivStartLoadTime = 0; private float _ivStartLoadTime = 0;
private float _nvStartLoadTime = 0;
private float _bvStartLoadTime = 0;
private float _spStartLoadTime = 0; private float _spStartLoadTime = 0;
public bool _splashLoaded = false; public bool _splashLoaded = false;
public bool _initialized { get; private set; } = false; public bool _initialized { get; private set; } = false;
@ -46,7 +47,7 @@ namespace WZ
MobileAds.Initialize(initStatus => MobileAds.Initialize(initStatus =>
{ {
if (_bannerAdUnits.Count > 0) LoadBanner(); LoadBanner();
if (_interstitialAdUnits.Count > 0) LoadInterstitial(); if (_interstitialAdUnits.Count > 0) LoadInterstitial();
if (_rewardedAdUnits.Count > 0) LoadRewarded(); if (_rewardedAdUnits.Count > 0) LoadRewarded();
if (_splashAdUnits.Count > 0) AdsSplashManager.Instance.InitSplash(); if (_splashAdUnits.Count > 0) AdsSplashManager.Instance.InitSplash();
@ -60,12 +61,14 @@ namespace WZ
public void RefreshAdsData() public void RefreshAdsData()
{ {
_bannerAdUnits = AdConfigParser.GetAdmobAdUnits(AdsType.Banner); _bannerAdUnits = AdConfigParser.GetAdmobAdUnits(AdsType.Banner);
_collapsibleBannerAdUnits = AdConfigParser.GetAdmobAdUnits(AdsType.Banner, BannerType.Collapsible);
_interstitialAdUnits = AdConfigParser.GetAdmobAdUnits(AdsType.Interstitial); _interstitialAdUnits = AdConfigParser.GetAdmobAdUnits(AdsType.Interstitial);
_nativeAdUnits = AdConfigParser.GetAdmobAdUnits(AdsType.Native); _nativeAdUnits = AdConfigParser.GetAdmobAdUnits(AdsType.Native);
_splashAdUnits = AdConfigParser.GetAdmobAdUnits(AdsType.Splash); _splashAdUnits = AdConfigParser.GetAdmobAdUnits(AdsType.Splash);
_rewardedAdUnits = AdConfigParser.GetAdmobAdUnits(AdsType.Rewarded); _rewardedAdUnits = AdConfigParser.GetAdmobAdUnits(AdsType.Rewarded);
_admobBannerAdManager?.ClearAds(_bannerAdUnits.ToArray()); _admobBannerAdManager?.ClearAds(_bannerAdUnits.ToArray());
_admobCollapsibleBannerAdManager?.ClearAds(_collapsibleBannerAdUnits.ToArray());
_admobInterstitialAdManager?.ClearAds(_interstitialAdUnits.ToArray()); _admobInterstitialAdManager?.ClearAds(_interstitialAdUnits.ToArray());
_admobNativeAdManager?.ClearAds(_nativeAdUnits.ToArray()); _admobNativeAdManager?.ClearAds(_nativeAdUnits.ToArray());
_admobSplashAdManager?.ClearAds(_splashAdUnits.ToArray()); _admobSplashAdManager?.ClearAds(_splashAdUnits.ToArray());
@ -341,58 +344,72 @@ namespace WZ
#region 广 #region 广
public void LoadBanner() public void LoadBanner()
{ {
_admobBannerAdManager?.Destroy(); LoadStandardBanner();
_admobBannerAdManager = new AdmobBannerAdManager(); LoadCollapsingBanner();
_admobBannerAdManager.InitializeAdUnits(BannerAliignType.BannerCenterBottomAlign,
_bannerAdUnits,
OnBannerAdLoaded,
OnBannerAdLoadFailed,
OnBannerAdPaid,
OnBannerAdClicked
);
_bvStartLoadTime = Time.realtimeSinceStartup;
AdsActionEvents.TrackAdStartLoad(Platfrom,AdsType.Banner); AdsActionEvents.TrackAdStartLoad(Platfrom,AdsType.Banner);
} }
public bool IsBannerAvailable() private void LoadStandardBanner()
{ {
if (!_initialized) return false; if (_bannerAdUnits.Count > 0)
return _admobBannerAdManager.GetAvailableAdUnits().Count > 0; {
} _admobBannerAdManager?.Destroy();
public void HideBanner() _admobBannerAdManager = new AdmobBannerAdManager();
{ _admobBannerAdManager.InitializeAdUnits(BannerAlignType.CenterBottom,_bannerAdUnits);
_admobBannerAdManager.HideBanner(); }
} }
public double GetBannerRevenue() public void LoadCollapsingBanner()
{
if (_collapsibleBannerAdUnits.Count > 0)
{
_admobCollapsibleBannerAdManager?.Destroy();
_admobCollapsibleBannerAdManager = new AdmobCollapsibleBannerAdManager();
_admobCollapsibleBannerAdManager.InitializeAdUnits(BannerAlignType.CenterBottom,_collapsibleBannerAdUnits);
}
}
public bool IsBannerAvailable(BannerType bannerType)
{
if (!_initialized) return false;
if (bannerType == BannerType.Standard)
{
return _admobBannerAdManager?.GetAvailableAdUnits().Count > 0;
}
else
{
return _admobCollapsibleBannerAdManager?.GetAvailableAdUnits().Count > 0;
}
}
public void HideBanner(BannerType bannerType)
{
if (bannerType == BannerType.Standard)
{
_admobBannerAdManager?.HideBanner();
}
else
{
_admobCollapsibleBannerAdManager?.HideBanner();
}
}
public double GetBannerRevenue(BannerType bannerType)
{ {
return _admobBannerAdManager.GetHighestPayingAdRevenue(); return _admobBannerAdManager.GetHighestPayingAdRevenue();
} }
public void DisplayBanner() public void DisplayBanner(BannerType bannerType,BannerAlignType bannerAlignType)
{ {
_admobBannerAdManager.ShowHighestPayingAd(); if (bannerType == BannerType.Standard)
} {
_admobBannerAdManager?.ShowHighestPayingAd(bannerAlignType);
private void OnBannerAdLoaded(string adSource,string adUnitId) }
{ else
{
AdsActionEvents.TrackAdLoaded(Platfrom,adSource,adUnitId,AdsType.Banner,Time.realtimeSinceStartup - _bvStartLoadTime); _admobCollapsibleBannerAdManager?.ShowHighestPayingAd(bannerAlignType);
} }
private void OnBannerAdLoadFailed(string adUnitId, int errorCode, string errorMsg)
{
AdsActionEvents.TrackAdFailToLoad(Platfrom,"","",AdsType.Banner,Time.realtimeSinceStartup - _bvStartLoadTime,errorMsg);
}
private void OnBannerAdClicked(string adSource,string adUnitId,double revenue)
{
AdsActionEvents.TrackAdClicked(Platfrom,adSource,adUnitId,AdsType.Banner,"",revenue);
}
private void OnBannerAdPaid(AdValue adValue)
{
} }
#endregion #endregion
@ -443,7 +460,7 @@ namespace WZ
/// <param name="adsType"></param> /// <param name="adsType"></param>
/// <param name="adUnitId"></param> /// <param name="adUnitId"></param>
/// <returns></returns> /// <returns></returns>
public bool FindAdsID(AdsType adsType, string adUnitId) public bool FindAdsID(AdsType adsType, string adUnitId,BannerType bannerType = BannerType.Standard)
{ {
if (adsType == AdsType.Rewarded) if (adsType == AdsType.Rewarded)
{ {
@ -463,7 +480,14 @@ namespace WZ
} }
else if (adsType == AdsType.Banner) else if (adsType == AdsType.Banner)
{ {
return _bannerAdUnits.Contains(adUnitId); if (bannerType == BannerType.Standard)
{
return _bannerAdUnits.Contains(adUnitId);
}
else
{
return _collapsibleBannerAdUnits.Contains(adUnitId);
}
} }
else else
{ {

View File

@ -25,7 +25,6 @@ namespace WZ
private Dictionary<string, NativeOverlayAd> _nativeAds = new Dictionary<string, NativeOverlayAd>(); private Dictionary<string, NativeOverlayAd> _nativeAds = new Dictionary<string, NativeOverlayAd>();
private Dictionary<string, double> _adRevenueCache = new Dictionary<string, double>(); private Dictionary<string, double> _adRevenueCache = new Dictionary<string, double>();
private Dictionary<string, int> _retryCounters = new Dictionary<string, int>(); private Dictionary<string, int> _retryCounters = new Dictionary<string, int>();
private Dictionary<string, float> _adStartLoadTimes = new Dictionary<string, float>(); private Dictionary<string, float> _adStartLoadTimes = new Dictionary<string, float>();
private Dictionary<string, ShowNativePosition> showingNativeAds = new(); private Dictionary<string, ShowNativePosition> showingNativeAds = new();

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ba10ede195dc84773add7e8daea165b5
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,6 +1,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using GoogleMobileAds.Api; using GoogleMobileAds.Api;
using System; using System;
using UnityEngine;
namespace WZ namespace WZ
{ {
@ -10,34 +11,28 @@ namespace WZ
private Dictionary<string, int> _retryCounters = new Dictionary<string, int>(); private Dictionary<string, int> _retryCounters = new Dictionary<string, int>();
private Dictionary<string, Action> _loadCallbacks = new Dictionary<string, Action>(); private Dictionary<string, Action> _loadCallbacks = new Dictionary<string, Action>();
private Dictionary<string, double> _adRevenueCache = new Dictionary<string, double>(); private Dictionary<string, double> _adRevenueCache = new Dictionary<string, double>();
private Dictionary<string, float> _adStartLoadTimes = new Dictionary<string, float>();
private BannerView _currentBannerView = null;
public void InitializeAdUnits(BannerAliignType type, List<string> adUnitIds, public void InitializeAdUnits(BannerAlignType type, List<string> adUnitIds)
Action<string,string> onAdLoaded = null,
Action<string,int, string> onAdLoadFailed = null,
Action<AdValue> OnAdPaid = null,
Action<string,string,double> onAdClicked = null)
{ {
foreach (var adUnitId in adUnitIds) foreach (var adUnitId in adUnitIds)
{ {
CreateRewardedAd(type, adUnitId, onAdLoaded, onAdLoadFailed,OnAdPaid, onAdClicked); CreateRewardedAd(type, adUnitId);
} }
} }
private void CreateRewardedAd(BannerAliignType type,string adUnitId, private void CreateRewardedAd(BannerAlignType type,string adUnitId)
Action<string,string> onAdLoaded,
Action<string,int, string> onAdLoadFailed,
Action<AdValue> OnAdPaid,
Action<string,string,double> onAdClicked)
{ {
if (string.IsNullOrEmpty(adUnitId)) return; if (string.IsNullOrEmpty(adUnitId)) return;
if (_bannerAds.ContainsKey(adUnitId)) if (_bannerAds.ContainsKey(adUnitId))
{ {
LoggerUtils.Debug($"Bigo banner Ad unit {adUnitId} already exists"); LoggerUtils.Debug($"[Admob] banner Ad unit {adUnitId} already exists");
return; return;
} }
var bannerAds = new BannerView(adUnitId, AdSize.Banner, type == BannerAliignType.BannerCenterBottomAlign ? AdPosition.Bottom : AdPosition.Top); var bannerAds = new BannerView(adUnitId, AdSize.Banner, type == BannerAlignType.CenterBottom ? AdPosition.Bottom : AdPosition.Top);
_adStartLoadTimes[adUnitId] = Time.realtimeSinceStartup;
bannerAds.Hide(); bannerAds.Hide();
_bannerAds[adUnitId] = bannerAds; _bannerAds[adUnitId] = bannerAds;
@ -49,8 +44,11 @@ namespace WZ
_retryCounters[adUnitId] = 0; _retryCounters[adUnitId] = 0;
_adRevenueCache[adUnitId] = AdmobUtils.GetBannerEcpm(bannerAds); _adRevenueCache[adUnitId] = AdmobUtils.GetBannerEcpm(bannerAds);
LoggerUtils.Debug($"[Admob] banner -[Load]: {adUnitId} successfully"); LoggerUtils.Debug($"[Admob] banner -[Load]: {adUnitId} successfully");
onAdLoaded?.Invoke(bannerAds.GetResponseInfo().GetLoadedAdapterResponseInfo().AdSourceName, AdsActionEvents.TrackAdLoaded(AdmobAdsManager.Instance.Platfrom,
adUnitId); bannerAds.GetResponseInfo().GetLoadedAdapterResponseInfo().AdSourceName,
adUnitId,
AdsType.Banner,
Time.realtimeSinceStartup - (_adStartLoadTimes.TryGetValue(adUnitId, out var time)? time : 0));
AdsKeyEvents.Instance.LogAdFPUEvents(AdsType.Banner); AdsKeyEvents.Instance.LogAdFPUEvents(AdsType.Banner);
}; };
@ -66,7 +64,11 @@ namespace WZ
// 延迟重试加载 // 延迟重试加载
_loadCallbacks[adUnitId] = () => LoadAd(adUnitId); _loadCallbacks[adUnitId] = () => LoadAd(adUnitId);
TimerUtils.Instance.DelayExecute((float)retryDelay, () => _loadCallbacks[adUnitId]?.Invoke()); TimerUtils.Instance.DelayExecute((float)retryDelay, () => _loadCallbacks[adUnitId]?.Invoke());
onAdLoadFailed?.Invoke(adUnitId, msg.GetCode(), msg.GetMessage()); AdsActionEvents.TrackAdFailToLoad(AdmobAdsManager.Instance.Platfrom,
"",
"",
AdsType.Banner,Time.realtimeSinceStartup - (_adStartLoadTimes.TryGetValue(adUnitId, out var time)? time : 0),
msg.GetMessage());
}); });
bannerAds.OnAdPaid += ((adValue) => bannerAds.OnAdPaid += ((adValue) =>
@ -76,14 +78,15 @@ namespace WZ
adValue, adValue,
AdsType.Banner, AdsType.Banner,
adUnitId); adUnitId);
OnAdPaid?.Invoke(adValue);
}); });
bannerAds.OnAdClicked += () => bannerAds.OnAdClicked += () =>
{ {
onAdClicked?.Invoke(bannerAds.GetResponseInfo().GetLoadedAdapterResponseInfo().AdSourceName, AdsActionEvents.TrackAdClicked(AdmobAdsManager.Instance.Platfrom,
bannerAds.GetResponseInfo().GetLoadedAdapterResponseInfo().AdSourceName,
adUnitId, adUnitId,
AdsType.Banner,
"",
AdmobUtils.GetBannerEcpm(bannerAds)); AdmobUtils.GetBannerEcpm(bannerAds));
}; };
LoadAd(adUnitId); LoadAd(adUnitId);
@ -102,38 +105,32 @@ namespace WZ
} }
// 显示价格最高的广告 // 显示价格最高的广告
public void ShowHighestPayingAd() public void ShowHighestPayingAd(BannerAlignType bannerAlignType)
{ {
var highestPayingAdUnit = GetHighestPayingAdUnit(); var highestPayingAdUnit = GetHighestPayingAdUnit();
if (!string.IsNullOrEmpty(highestPayingAdUnit)) if (!string.IsNullOrEmpty(highestPayingAdUnit))
{ {
ShowAd(highestPayingAdUnit); ShowAd(highestPayingAdUnit, bannerAlignType);
} }
} }
public void HideBanner() public void HideBanner()
{ {
_currentBannerView?.Hide();
var highestPayingAdUnit = GetHighestPayingAdUnit();
if (!string.IsNullOrEmpty(highestPayingAdUnit))
{
if (_bannerAds.TryGetValue(highestPayingAdUnit, out var ad))
{
ad.Hide();
}
}
} }
// 显示特定广告位的广告 // 显示特定广告位的广告
private void ShowAd(string adUnitId) private void ShowAd(string adUnitId,BannerAlignType bannerAlignType)
{ {
if (!AdmobAdsManager.Instance.FindAdsID(AdsType.Banner, adUnitId)) if (!AdmobAdsManager.Instance.FindAdsID(AdsType.Banner, adUnitId))
{ {
return; return;
} }
if (_bannerAds.TryGetValue(adUnitId, out var ad)) if (_bannerAds.TryGetValue(adUnitId, out var ad))
{ {
ad.SetPosition(bannerAlignType == BannerAlignType.CenterBottom ? AdPosition.Bottom : AdPosition.Top);
ad.Show(); ad.Show();
_currentBannerView = ad;
} }
} }
@ -162,7 +159,7 @@ namespace WZ
public string GetHighestPayingAdUnit() public string GetHighestPayingAdUnit()
{ {
string highestPayingAdUnit = null; string highestPayingAdUnit = null;
double highestRevenue = 0; double highestRevenue = -1;
foreach (var kvp in _adRevenueCache) foreach (var kvp in _adRevenueCache)
{ {

View File

@ -0,0 +1,236 @@
using System.Collections.Generic;
using GoogleMobileAds.Api;
using System;
using UnityEngine;
namespace WZ
{
public class AdmobCollapsibleBannerAdManager
{
private Dictionary<string, BannerView> _bannerAds = new Dictionary<string, BannerView>();
private Dictionary<string, int> _retryCounters = new Dictionary<string, int>();
private Dictionary<string, Action> _loadCallbacks = new Dictionary<string, Action>();
private Dictionary<string, double> _adRevenueCache = new Dictionary<string, double>();
private Dictionary<string, float> _adStartLoadTimes = new Dictionary<string, float>();
private BannerView _currentBannerView = null;
public void InitializeAdUnits(BannerAlignType type, List<string> adUnitIds)
{
foreach (var adUnitId in adUnitIds)
{
CreateRewardedAd(type, adUnitId);
}
}
private void CreateRewardedAd(BannerAlignType type,string adUnitId)
{
if (string.IsNullOrEmpty(adUnitId)) return;
if (_bannerAds.ContainsKey(adUnitId))
{
LoggerUtils.Debug($"[Admob] banner collapsible Ad unit {adUnitId} already exists");
return;
}
var bannerAds = new BannerView(adUnitId, AdSize.Banner, type == BannerAlignType.CenterBottom ? AdPosition.Bottom : AdPosition.Top);
_adStartLoadTimes[adUnitId] = Time.realtimeSinceStartup;
bannerAds.Hide();
_bannerAds[adUnitId] = bannerAds;
_retryCounters[adUnitId] = 0;
_adRevenueCache[adUnitId] = 0;
bannerAds.OnBannerAdLoaded += () =>
{
_retryCounters[adUnitId] = 0;
_adRevenueCache[adUnitId] = AdmobUtils.GetBannerEcpm(bannerAds);
LoggerUtils.Debug($"[Admob] banner collapsible -[Load]: {adUnitId} successfully iscollapsible: {bannerAds.IsCollapsible()}");
AdsActionEvents.TrackAdLoaded(AdmobAdsManager.Instance.Platfrom,
bannerAds.GetResponseInfo().GetLoadedAdapterResponseInfo().AdSourceName,
adUnitId,
AdsType.Banner,
Time.realtimeSinceStartup - (_adStartLoadTimes.TryGetValue(adUnitId, out var time)? time : 0));
AdsKeyEvents.Instance.LogAdFPUEvents(AdsType.Banner);
};
bannerAds.OnBannerAdLoadFailed += ((msg) =>
{
if (!_retryCounters.TryAdd(adUnitId, 0))
{
_retryCounters[adUnitId]++;
}
double retryDelay = Math.Pow(2, Math.Min(6, _retryCounters[adUnitId]));
LoggerUtils.Debug($"[Admob] banner collapsible -[Load]: {adUnitId} failed, error message = {msg}");
// 延迟重试加载
_loadCallbacks[adUnitId] = () => LoadAd(adUnitId);
TimerUtils.Instance.DelayExecute((float)retryDelay, () => _loadCallbacks[adUnitId]?.Invoke());
AdsActionEvents.TrackAdFailToLoad(AdmobAdsManager.Instance.Platfrom,
"",
"",
AdsType.Banner,Time.realtimeSinceStartup - (_adStartLoadTimes.TryGetValue(adUnitId, out var time)? time : 0),
msg.GetMessage());
});
bannerAds.OnAdPaid += ((adValue) =>
{
LoggerUtils.Debug($"[Admob] banner collapsible -[interaction]: {adUnitId} show");
AdmobAdsManager.Instance.TrackAdImpression(bannerAds.GetResponseInfo().GetLoadedAdapterResponseInfo(),
adValue,
AdsType.Banner,
adUnitId);
});
bannerAds.OnAdClicked += () =>
{
AdsActionEvents.TrackAdClicked(AdmobAdsManager.Instance.Platfrom,
bannerAds.GetResponseInfo().GetLoadedAdapterResponseInfo().AdSourceName,
adUnitId,
AdsType.Banner,
"",
AdmobUtils.GetBannerEcpm(bannerAds));
};
LoadAd(adUnitId);
}
public void LoadAd(string adUnitId)
{
if (!AdmobAdsManager.Instance.FindAdsID(AdsType.Banner, adUnitId,BannerType.Collapsible))
{
return;
}
if (_bannerAds.TryGetValue(adUnitId, out var ad))
{
var adRequest = new AdRequest();
adRequest.Extras.Add("collapsible", "bottom");
ad.LoadAd(adRequest);
}
}
// 显示价格最高的广告
public void ShowHighestPayingAd(BannerAlignType bannerAlignType)
{
var highestPayingAdUnit = GetHighestPayingAdUnit();
if (!string.IsNullOrEmpty(highestPayingAdUnit))
{
ShowAd(highestPayingAdUnit,bannerAlignType);
}
}
public void HideBanner()
{
_currentBannerView?.Hide();
_currentBannerView?.Destroy();
AdmobAdsManager.Instance.LoadCollapsingBanner();
}
// 显示特定广告位的广告
private void ShowAd(string adUnitId,BannerAlignType bannerAlignType)
{
if (!AdmobAdsManager.Instance.FindAdsID(AdsType.Banner, adUnitId,BannerType.Collapsible))
{
return;
}
if (_bannerAds.TryGetValue(adUnitId, out var ad))
{
ad.SetPosition(bannerAlignType == BannerAlignType.CenterBottom ? AdPosition.Bottom : AdPosition.Top);
ad.Show();
_currentBannerView = ad;
}
}
// 获取所有可用的广告位
public List<string> GetAvailableAdUnits()
{
var available = new List<string>();
foreach (var kvp in _bannerAds)
{
available.Add(kvp.Key);
}
return available;
}
// 获取特定广告位的收益信息
public double GetAdRevenue(string adUnitId)
{
if (_adRevenueCache.TryGetValue(adUnitId, out var revenue))
{
return revenue;
}
return 0;
}
// 获取价格最高的广告位ID
public string GetHighestPayingAdUnit()
{
string highestPayingAdUnit = null;
double highestRevenue = -1;
foreach (var kvp in _adRevenueCache)
{
var adUnitId = kvp.Key;
var revenue = kvp.Value;
// 确保广告确实已加载并且价格更高
if (revenue > highestRevenue)
{
highestRevenue = revenue;
highestPayingAdUnit = adUnitId;
}
}
return highestPayingAdUnit;
}
// 获取价格最高的广告收益信息
public double GetHighestPayingAdRevenue()
{
var highestPayingAdUnit = GetHighestPayingAdUnit();
if (!string.IsNullOrEmpty(highestPayingAdUnit) &&
_adRevenueCache.TryGetValue(highestPayingAdUnit, out var revenue))
{
return revenue;
}
return 0;
}
// 清理资源
public void Destroy()
{
foreach (var ad in _bannerAds.Values)
{
ad.Destroy();
}
_bannerAds.Clear();
_retryCounters.Clear();
_loadCallbacks.Clear();
_adRevenueCache.Clear();
}
public void ClearAds(string[] adUnitIds)
{
// 将数组转换为HashSet以提高查找性能
HashSet<string> validKeys = new HashSet<string>(adUnitIds);
// 收集需要移除的key
List<string> keysToRemove = new List<string>();
foreach (var key in _bannerAds.Keys)
{
if (!validKeys.Contains(key))
{
keysToRemove.Add(key);
}
}
// 移除不在数组中的key
foreach (string key in keysToRemove)
{
_bannerAds.Remove(key);
_retryCounters.Remove(key);
_loadCallbacks.Remove(key);
_adRevenueCache.Remove(key);
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c92ae3b763c614567a435a03e5571311
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -27,10 +27,10 @@ namespace WZ
private void InitializeAdNetworks() private void InitializeAdNetworks()
{ {
_adNetworks.Add(AdmobAdsManager.Instance); // _adNetworks.Add(AdmobAdsManager.Instance);
_adNetworks.Add(BigoAdsManager.Instance); // _adNetworks.Add(BigoAdsManager.Instance);
_adNetworks.Add(TpnAdsManager.Instance); // _adNetworks.Add(TpnAdsManager.Instance);
_adNetworks.Add(MaxAdsManager.Instance); // _adNetworks.Add(MaxAdsManager.Instance);
_adNetworks.Add(KwaiAdsManager.Instance); _adNetworks.Add(KwaiAdsManager.Instance);
foreach (var network in _adNetworks) foreach (var network in _adNetworks)
{ {
@ -221,22 +221,22 @@ namespace WZ
#endregion #endregion
#region 广 #region 广
public bool IsBannerAdReady() public bool IsBannerAdReady(BannerType bannerType)
{ {
return AdmobAdsManager.Instance.IsBannerAvailable(); return AdmobAdsManager.Instance.IsBannerAvailable(bannerType);
} }
public void ShowBanner() public void ShowBanner(BannerType bannerType,BannerAlignType bannerAlignType)
{ {
AdmobAdsManager.Instance.DisplayBanner(); AdmobAdsManager.Instance.DisplayBanner(bannerType,bannerAlignType);
AdPlayCountManager.IncrementAdsActionCount(AdsType.Banner,AdPlayCountManager.PLAY_COUNT_SUFFIX); AdPlayCountManager.IncrementAdsActionCount(AdsType.Banner,AdPlayCountManager.PLAY_COUNT_SUFFIX);
AdjustTrackEvent.Instance.TrackEventName("Banner_Show", new Dictionary<string, object>()); AdjustTrackEvent.Instance.TrackEventName("Banner_Show", new Dictionary<string, object>());
} }
public void HideBanner() public void HideBanner(BannerType bannerType)
{ {
AdmobAdsManager.Instance.HideBanner(); AdmobAdsManager.Instance.HideBanner(bannerType);
} }
#endregion #endregion
@ -295,9 +295,9 @@ namespace WZ
if (isInterstitial) if (isInterstitial)
{ {
AdPriceInfo priceInfo = new AdPriceInfo( AdPriceInfo priceInfo = new AdPriceInfo(
maxPrice: MaxAdsManager.Instance.GetInterstitialRevenue(), maxPrice: -1,//MaxAdsManager.Instance.GetInterstitialRevenue(),
admobPrice: AdmobAdsManager.Instance.GetInterstitialRevenue(), admobPrice: -1,//AdmobAdsManager.Instance.GetInterstitialRevenue(),
bigoPrice: BigoAdsManager.Instance.GetInterstitialRevenue(), bigoPrice: -1,//BigoAdsManager.Instance.GetInterstitialRevenue(),
kwaiPrice: KwaiAdsManager.Instance.GetInterstitialRevenue(), kwaiPrice: KwaiAdsManager.Instance.GetInterstitialRevenue(),
toponAdUnitId: TpnAdsManager.Instance._topon_interstitial_units toponAdUnitId: TpnAdsManager.Instance._topon_interstitial_units
); );
@ -306,9 +306,9 @@ namespace WZ
else else
{ {
AdPriceInfo priceInfo = new AdPriceInfo( AdPriceInfo priceInfo = new AdPriceInfo(
maxPrice: MaxAdsManager.Instance.GetRewardedRevenue(), maxPrice: -1,//MaxAdsManager.Instance.GetRewardedRevenue(),
admobPrice: AdmobAdsManager.Instance.GetRewardedRevenue(), admobPrice: -1,//AdmobAdsManager.Instance.GetRewardedRevenue(),
bigoPrice: BigoAdsManager.Instance.GetRewardedRevenue(), bigoPrice: -1,//BigoAdsManager.Instance.GetRewardedRevenue(),
kwaiPrice: KwaiAdsManager.Instance.GetRewardedRevenue(), kwaiPrice: KwaiAdsManager.Instance.GetRewardedRevenue(),
toponAdUnitId: TpnAdsManager.Instance._topon_rewarded_units toponAdUnitId: TpnAdsManager.Instance._topon_rewarded_units
); );

View File

@ -250,10 +250,10 @@ namespace WZ
#region 广 #region 广
public void LoadBanner() { } public void LoadBanner() { }
public bool IsBannerAvailable() { return false; } public bool IsBannerAvailable(BannerType bannerType) { return false; }
public void DisplayBanner() { } public void DisplayBanner(BannerType bannerType,BannerAlignType bannerAlignType) { }
public void HideBanner() { } public void HideBanner(BannerType bannerType) { }
public double GetBannerRevenue() { return 0; } public double GetBannerRevenue(BannerType bannerType) { return 0; }
#endregion #endregion

View File

@ -4,10 +4,12 @@ using UnityEngine;
namespace WZ namespace WZ
{ {
public enum BannerAliignType public enum BannerAlignType
{ {
BannerCenterBottomAlign = 0, // 底部居中
BannerCenterTopAlign = 1, CenterBottom = 0,
// 顶部居中
CenterTop = 1,
} }
} }

View File

@ -0,0 +1,16 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace WZ
{
public enum BannerType
{
// 普通banner
Standard,
// 可折叠banner
Collapsible
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c4c8c6aa996184304b22cfa074be8873
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -222,10 +222,10 @@ namespace WZ
#region 广 #region 广
public void LoadBanner() { } public void LoadBanner() { }
public bool IsBannerAvailable() { return false; } public bool IsBannerAvailable(BannerType bannerType) { return false; }
public void DisplayBanner() { } public void DisplayBanner(BannerType bannerType,BannerAlignType bannerAlignType) { }
public void HideBanner() { } public void HideBanner(BannerType bannerType) { }
public double GetBannerRevenue() { return 0; } public double GetBannerRevenue(BannerType bannerType) { return 0; }
#endregion #endregion
#region 广 #region 广

View File

@ -418,10 +418,10 @@ namespace WZ
#region 广 #region 广
public void LoadBanner() { } public void LoadBanner() { }
public bool IsBannerAvailable() { return false; } public bool IsBannerAvailable(BannerType bannerType) { return false; }
public void HideBanner() { } public void HideBanner(BannerType bannerType) { }
public double GetBannerRevenue() { return 0; } public double GetBannerRevenue(BannerType bannerType) { return 0; }
public void DisplayBanner() { } public void DisplayBanner(BannerType bannerType,BannerAlignType bannerAlignType) { }
#endregion #endregion
#region 广 #region 广

View File

@ -284,10 +284,10 @@ namespace WZ
#region 广 #region 广
public void LoadBanner() { } public void LoadBanner() { }
public bool IsBannerAvailable() { return false; } public bool IsBannerAvailable(BannerType bannerType) { return false; }
public void HideBanner() { } public void HideBanner(BannerType bannerType) { }
public double GetBannerRevenue() { return 0; } public double GetBannerRevenue(BannerType bannerType) { return 0; }
public void DisplayBanner() { } public void DisplayBanner(BannerType bannerType,BannerAlignType bannerAlignType) { }
#endregion #endregion
#region 广 #region 广

View File

@ -51,19 +51,27 @@ namespace WZ
/// <summary> /// <summary>
/// 获取 Admob 广告单元ID /// 获取 Admob 广告单元ID
/// </summary> /// </summary>
public static List<string> GetAdmobAdUnits(AdsType adType) public static List<string> GetAdmobAdUnits(AdsType adType, BannerType bannerType = BannerType.Standard)
{ {
if (_config == null) if (_config == null)
{ {
return adType switch
switch (adType)
{ {
AdsType.Banner => new List<string> { StaticValue.AdmobNormalBannerId }, case AdsType.Banner:
AdsType.Rewarded => new List<string> { StaticValue.AdmobRewardId }, if (bannerType == BannerType.Standard) return new List<string>() { StaticValue.AdmobNormalBannerId};
AdsType.Native => new List<string> { StaticValue.AdmobNativeId, StaticValue.AdmobMinddleNativeId, StaticValue.AdmobSmallNativeId, StaticValue.AdmobFullNativeId }, else return new List<string> { StaticValue.AdmobCollapsibleBannerId };
AdsType.Splash => new List<string> { StaticValue.AdmobSplashId }, case AdsType.Rewarded:
AdsType.Interstitial => new List<string> { StaticValue.AdmobInterId }, return new List<string> { StaticValue.AdmobRewardId };
_ => new List<string>() case AdsType.Native:
}; return new List<string> { StaticValue.AdmobNativeId, StaticValue.AdmobMinddleNativeId, StaticValue.AdmobSmallNativeId, StaticValue.AdmobFullNativeId };
case AdsType.Splash:
return new List<string> { StaticValue.AdmobSplashId };
case AdsType.Interstitial:
return new List<string> { StaticValue.AdmobInterId };
default:
return new List<string>();
}
} }
switch (adType) switch (adType)
@ -73,9 +81,20 @@ namespace WZ
{ {
return _config.admob_banner_units ?? new List<string>(); return _config.admob_banner_units ?? new List<string>();
} }
else if (_configDict.ContainsKey("admob_normal_banner_units"))
{
return _config.admob_collbanner_units ?? new List<string>();
}
else else
{ {
return new List<string>{ StaticValue.AdmobNormalBannerId }; if (bannerType == BannerType.Standard)
{
return new List<string> { StaticValue.AdmobNormalBannerId };
}
else
{
return new List<string> { StaticValue.AdmobCollapsibleBannerId };
}
} }
case AdsType.Rewarded: case AdsType.Rewarded:
if (_configDict.ContainsKey("admob_rewarded_units")) if (_configDict.ContainsKey("admob_rewarded_units"))
@ -83,8 +102,8 @@ namespace WZ
return _config.admob_rewarded_units ?? new List<string>(); return _config.admob_rewarded_units ?? new List<string>();
} }
else else
{ {
return new List<string>{ StaticValue.AdmobRewardId }; return new List<string> { StaticValue.AdmobRewardId };
} }
case AdsType.Native: case AdsType.Native:
if (_configDict.ContainsKey("admob_native_units")) if (_configDict.ContainsKey("admob_native_units"))
@ -92,7 +111,7 @@ namespace WZ
return _config.admob_native_units ?? new List<string>(); return _config.admob_native_units ?? new List<string>();
} }
else else
{ {
return new List<string>{ StaticValue.AdmobNativeId, return new List<string>{ StaticValue.AdmobNativeId,
StaticValue.AdmobMinddleNativeId, StaticValue.AdmobMinddleNativeId,
StaticValue.AdmobSmallNativeId, StaticValue.AdmobSmallNativeId,
@ -104,8 +123,8 @@ namespace WZ
return _config.admob_splash_units ?? new List<string>(); return _config.admob_splash_units ?? new List<string>();
} }
else else
{ {
return new List<string>{ StaticValue.AdmobSplashId }; return new List<string> { StaticValue.AdmobSplashId };
} }
case AdsType.Interstitial: case AdsType.Interstitial:
if (_configDict.ContainsKey("admob_interstitial_units")) if (_configDict.ContainsKey("admob_interstitial_units"))
@ -113,10 +132,10 @@ namespace WZ
return _config.admob_interstitial_units ?? new List<string>(); return _config.admob_interstitial_units ?? new List<string>();
} }
else else
{ {
return new List<string>{ StaticValue.AdmobInterId }; return new List<string> { StaticValue.AdmobInterId };
} }
default: default:
return new List<string>(); return new List<string>();
@ -334,6 +353,7 @@ namespace WZ
public List<string> admob_splash_units; public List<string> admob_splash_units;
public List<string> admob_rewarded_units; public List<string> admob_rewarded_units;
public List<string> admob_banner_units; public List<string> admob_banner_units;
public List<string> admob_collbanner_units;
public List<string> admob_native_units; public List<string> admob_native_units;
// TopOn 配置 // TopOn 配置

View File

@ -180,23 +180,28 @@ public class RushSDKManager : D_MonoSingleton<RushSDKManager>
} }
} }
public void ShowBanner() /// <summary>
///
/// </summary>
/// <param name="bannerType">banner样式Standard普通bannerCollapsible可折叠banner</param>
/// <param name="bannerAlignType">banner位置CenterBottom底部居中CenterTop顶部居中</param>
public void ShowBanner(BannerType bannerType, BannerAlignType bannerAlignType)
{ {
AdsActionEvents.TrackAdPosition(AdsType.Banner, ""); AdsActionEvents.TrackAdPosition(AdsType.Banner, "");
if (AdsSDKManager.Instance.IsBannerAdReady())
if (AdsSDKManager.Instance.IsBannerAdReady(bannerType))
{ {
AdsSDKManager.Instance.ShowBanner(); AdsSDKManager.Instance.ShowBanner(bannerType, bannerAlignType);
} }
else else
{ {
AdsActionEvents.TrackAdFailToShow(AdsType.Banner, "", AdsShowFailType.NoFill); AdsActionEvents.TrackAdFailToShow(AdsType.Banner, "", AdsShowFailType.NoFill);
} }
} }
public void HideBanner() public void HideBanner(BannerType bannerType)
{ {
AdsSDKManager.Instance.HideBanner(); AdsSDKManager.Instance.HideBanner(bannerType);
} }
public bool IsNativeFullReady() public bool IsNativeFullReady()

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 1c4c2222d1fbb4a95ac19d4849cff0e6
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,14 @@
# Version 1.0.1 2025.9.16
## Bugs
- None
## Known issues
- None
## Changelog
- 新增Kwai广告位竞价逻辑
- 新增跳转谷歌商店接口
- 新增adjust用户来源回调
- 新增隐私协议接口
- 优化native样式
- 新增native自刷新功能
- 支持Admob可折叠banner

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: e7a9965fdd7874369a19207565134a1a
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant: