diff --git a/Assets/Script/Common.meta b/Assets/Script/Common.meta
new file mode 100644
index 0000000..65c3ccb
--- /dev/null
+++ b/Assets/Script/Common.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: f29d03f26edcc4074b581c302af83455
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Script/Common/IAdService.cs b/Assets/Script/Common/IAdService.cs
new file mode 100644
index 0000000..9b8426f
--- /dev/null
+++ b/Assets/Script/Common/IAdService.cs
@@ -0,0 +1,195 @@
+using System;
+namespace Script.Common
+{
+ ///
+ /// 提供广告SDK功能的统一接口
+ ///
+ public interface IAdService
+ {
+ ///
+ /// 获取广告客户端名称
+ ///
+ string ClientName { get; }
+
+ ///
+ /// 初始化广告SDK
+ ///
+ void Initialize();
+
+ #region 横幅广告功能
+
+ ///
+ /// 加载横幅广告
+ ///
+ void LoadBanner();
+
+ ///
+ /// 检查横幅广告是否可用
+ ///
+ bool IsBannerAvailable();
+
+ ///
+ /// 显示横幅广告
+ ///
+ void DisplayBanner();
+
+ ///
+ /// 隐藏横幅广告
+ ///
+ void HideBanner();
+
+ ///
+ /// 获取横幅广告收益信息
+ ///
+ double GetBannerRevenue();
+
+ #endregion
+
+ #region 插页广告功能
+
+ ///
+ /// 加载插页广告
+ ///
+ void LoadInterstitial();
+
+ ///
+ /// 检查插页广告是否可用
+ ///
+ bool IsInterstitialAvailable();
+
+ ///
+ /// 显示插页广告
+ ///
+ void DisplayInterstitial();
+
+ ///
+ /// 获取插页广告收益信息
+ ///
+ double GetInterstitialRevenue();
+
+ #endregion
+
+ #region 激励广告功能
+
+ ///
+ /// 加载激励广告
+ ///
+ void LoadRewarded();
+
+ ///
+ /// 检查激励广告是否可用
+ ///
+ bool IsRewardedAvailable();
+
+ ///
+ /// 显示激励广告
+ ///
+ void DisplayRewarded();
+
+ ///
+ /// 获取激励广告收益信息
+ ///
+ double GetRewardedRevenue();
+
+ #endregion
+
+ #region 开屏广告功能
+
+ ///
+ /// 加载开屏广告
+ ///
+ void LoadSplash();
+
+ ///
+ /// 检查开屏广告是否可用
+ ///
+ bool IsSplashAvailable();
+
+ ///
+ /// 显示开屏广告
+ ///
+ void DisplaySplash();
+
+ ///
+ /// 获取开屏广告收益信息
+ ///
+ double GetSplashRevenue();
+
+ #endregion
+
+ #region 原生广告功能
+
+ ///
+ /// 加载原生广告
+ ///
+ void LoadNative();
+
+ ///
+ /// 检查原生广告是否可用
+ ///
+ bool IsNativeAvailable();
+
+ ///
+ /// 显示原生广告
+ ///
+ /// 广告位置和尺寸信息
+ void DisplayNative(NativeAdPosition position);
+
+ ///
+ /// 移除原生广告
+ ///
+ void RemoveNative();
+
+ ///
+ /// 获取原生广告收益信息
+ ///
+ double GetNativeRevenue();
+
+ #endregion
+ }
+
+ ///
+ /// 表示处理回调的信息
+ ///
+ [Serializable]
+ public struct CallbackResult
+ {
+ ///
+ /// 回调消息
+ ///
+ public string Message;
+
+ ///
+ /// 指示广告是否准备就绪
+ ///
+ public bool IsReady;
+ }
+
+ ///
+ /// 表示原生广告的位置和尺寸
+ ///
+ [Serializable]
+ public class NativeAdPosition
+ {
+ ///
+ /// X坐标
+ ///
+ public int X;
+
+ ///
+ /// Y坐标
+ ///
+ public int Y;
+
+ ///
+ /// 广告宽度
+ ///
+ public int Width;
+
+ ///
+ /// 广告高度
+ ///
+ public int Height;
+ }
+
+}
diff --git a/Assets/Script/Common/IAdService.cs.meta b/Assets/Script/Common/IAdService.cs.meta
new file mode 100644
index 0000000..6be5b9e
--- /dev/null
+++ b/Assets/Script/Common/IAdService.cs.meta
@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: 8c783da4d1e92421e875e007d834b039
\ No newline at end of file
diff --git a/Assets/Script/SDKManager/AdsSDKManager/BigoAdsManager.meta b/Assets/Script/SDKManager/AdsSDKManager/BigoAdsManager.meta
new file mode 100644
index 0000000..6c7d0f9
--- /dev/null
+++ b/Assets/Script/SDKManager/AdsSDKManager/BigoAdsManager.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: cdbba6a75dfa94e48af5d951115e1816
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Script/SDKManager/AdsSDKManager/BigoAdsManager/BigoAdsManager.cs b/Assets/Script/SDKManager/AdsSDKManager/BigoAdsManager/BigoAdsManager.cs
new file mode 100644
index 0000000..a9a7a86
--- /dev/null
+++ b/Assets/Script/SDKManager/AdsSDKManager/BigoAdsManager/BigoAdsManager.cs
@@ -0,0 +1,219 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using BigoAds.Scripts.Api;
+using Script.Common;
+using Script.Utils;
+using SDK.Utils;
+using Unity.VisualScripting;
+using UnityEngine;
+
+
+namespace Script.SDKManager.AdsSDKManager.BigoAdsManager
+{
+ public class BigoAdsManager : NormalSingleton, IAdService
+ {
+ public string ClientName => "BigoAds";
+ private BigoRewardedAdManager _rewardedAdManager;
+ private BigoInterstitialAdManager _interstitialAdManager;
+ private List _interstitialAdUnits;
+ private List _rewardedAdUnits;
+ public string bigo_app_id;
+
+ public void Initialize()
+ {
+ if (string.IsNullOrEmpty(bigo_app_id)) return;
+ _rewardedAdUnits = GetRewardedAdUnitsFromServer();
+ _interstitialAdUnits = GetInterstitialAdUnitsFromServer();
+ BigoAdSdk.OnInitFinish += () =>
+ {
+ LoggerUtils.Debug($" bigo sdk init success");
+ _rewardedAdManager = new BigoRewardedAdManager();
+ _rewardedAdManager.InitializeAdUnits(
+ _rewardedAdUnits,
+ onAdLoaded: OnRewardedAdLoaded,
+ onAdLoadFailed: OnRewardedAdLoadFailed,
+ onAdShowed: OnRewardedAdShowed,
+ onAdDismissed: OnRewardedAdDismissed,
+ onAdError: OnRewardedAdError,
+ onAdClicked: OnRewardedAdClicked
+ );
+ _interstitialAdManager = new BigoInterstitialAdManager();
+ _interstitialAdManager.InitializeAdUnits(
+ _interstitialAdUnits,
+ onAdLoaded: OnInterstitialAdLoaded,
+ onAdLoadFailed: OnInterstitialAdLoadFailed,
+ onAdShowed: OnInterstitialAdShowed,
+ onAdDismissed: OnInterstitialAdDismissed,
+ onAdError: OnInterstitialAdError,
+ onAdClicked: OnInterstitialAdClicked
+ );
+ };
+ // todo
+ var config = new BigoAdConfig.Builder()
+ .SetAppId(bigo_app_id)
+ .SetDebugLog(false)
+ .Build();
+ BigoAdSdk.Initialize(config);
+ }
+
+ #region Rewarded
+ // 各个回调处理方法
+ private void OnRewardedAdLoaded(string adUnitId)
+ {
+
+ }
+
+ private void OnRewardedAdLoadFailed(string adUnitId, int code, string msg)
+ {
+
+ }
+
+ private void OnRewardedAdShowed(string adUnitId)
+ {
+
+ }
+ private void OnRewardedAdDismissed(string adUnitId)
+ {
+ _rewardedAdManager.Destroy();
+ LoadRewarded();
+ }
+
+ private void OnRewardedAdError(string adUnitId, int code, string msg)
+ {
+
+ }
+
+ private void OnRewardedAdClicked()
+ {
+
+ }
+
+ public void LoadRewarded()
+ {
+
+ foreach (var adUnitId in _rewardedAdUnits)
+ {
+ _rewardedAdManager.LoadAd(adUnitId);
+ }
+ }
+
+ public bool IsRewardedAvailable()
+ {
+ return _rewardedAdManager.GetAvailableAdUnits().Count > 0;
+ }
+
+ public void DisplayRewarded()
+ {
+ _rewardedAdManager.ShowHighestPayingAd();
+ }
+
+ public double GetRewardedRevenue()
+ {
+ return _rewardedAdManager.GetHighestPayingAdRevenue();
+ }
+
+ // 从服务器获取广告位配置
+ private List GetRewardedAdUnitsFromServer()
+ {
+ // todo
+ return new List { "bigo_reward_unit_1", "bigo_reward_unit_2", "bigo_reward_unit_3" };
+ }
+
+ #region Interstitial
+ private void OnInterstitialAdLoaded(string adUnitId)
+ {
+
+ }
+
+ private void OnInterstitialAdLoadFailed(string adUnitId, int code, string msg)
+ {
+
+ }
+
+ private void OnInterstitialAdShowed(string adUnitId)
+ {
+
+ }
+ private void OnInterstitialAdDismissed(string adUnitId)
+ {
+ _interstitialAdManager.Destroy();
+ LoadInterstitial();
+ }
+
+ private void OnInterstitialAdError(string adUnitId, int code, string msg)
+ {
+
+ }
+
+ private void OnInterstitialAdClicked()
+ {
+
+ }
+
+ public void LoadInterstitial()
+ {
+ foreach (var adUnitId in _interstitialAdUnits)
+ {
+ _interstitialAdManager.LoadAd(adUnitId);
+ }
+ }
+
+ public bool IsInterstitialAvailable()
+ {
+ // 检查是否有任意一个广告位可用
+ return _interstitialAdManager.GetAvailableAdUnits().Count > 0;
+ }
+
+ public void DisplayInterstitial()
+ {
+ _interstitialAdManager.ShowHighestPayingAd();
+ }
+
+ public double GetInterstitialRevenue()
+ {
+ return _interstitialAdManager.GetHighestPayingAdRevenue();
+ }
+
+ // 从服务器获取广告位配置
+ private List GetInterstitialAdUnitsFromServer()
+ {
+ // 实现从服务器获取广告位ID列表的逻辑
+ // todo
+ return new List { "bigo_interstitial_unit_1", "bigo_interstitial_unit_2", "bigo_interstitial_unit_3" };
+ }
+
+ #endregion
+
+ #region 开屏广告
+
+ public void LoadSplash() { }
+ public bool IsSplashAvailable() { return false; }
+ public void DisplaySplash() { }
+ public double GetSplashRevenue() { return 0; }
+
+ #endregion
+
+ #region 原生广告功能
+ public void LoadNative() { }
+ public bool IsNativeAvailable() { return false; }
+ public void DisplayNative(NativeAdPosition position) { }
+ public void RemoveNative() { }
+ public double GetNativeRevenue() { return 0; }
+
+ #endregion
+
+ #region 横幅广告功能
+ public void LoadBanner() { }
+ public bool IsBannerAvailable() { return false; }
+ public void DisplayBanner() { }
+ public void HideBanner() { }
+ public double GetBannerRevenue() { return 0; }
+
+ #endregion
+ }
+
+ #endregion
+
+}
+
diff --git a/Assets/Script/SDKManager/AdsSDKManager/BigoAdsManager/BigoAdsManager.cs.meta b/Assets/Script/SDKManager/AdsSDKManager/BigoAdsManager/BigoAdsManager.cs.meta
new file mode 100644
index 0000000..e92ae5e
--- /dev/null
+++ b/Assets/Script/SDKManager/AdsSDKManager/BigoAdsManager/BigoAdsManager.cs.meta
@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: 32bd7a6ecbc5e48da929eb774391fe49
\ No newline at end of file
diff --git a/Assets/Script/SDKManager/AdsSDKManager/BigoAdsManager/BigoInterstitialAdManager.cs b/Assets/Script/SDKManager/AdsSDKManager/BigoAdsManager/BigoInterstitialAdManager.cs
new file mode 100644
index 0000000..fa091ea
--- /dev/null
+++ b/Assets/Script/SDKManager/AdsSDKManager/BigoAdsManager/BigoInterstitialAdManager.cs
@@ -0,0 +1,209 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using BigoAds.Scripts.Api;
+using Script.Utils;
+using UnityEngine;
+
+namespace Script.SDKManager.AdsSDKManager.BigoAdsManager
+{
+
+ public class BigoInterstitialAdManager
+ {
+ private Dictionary _interstitialAds = new Dictionary();
+ private Dictionary _retryCounters = new Dictionary();
+ private Dictionary _loadCallbacks = new Dictionary();
+ private Dictionary _adRevenueCache = new Dictionary();
+
+ public void InitializeAdUnits(List adUnitIds, Action onAdLoaded = null,
+ Action onAdLoadFailed = null,
+ Action onAdShowed = null,
+ Action onAdDismissed = null,
+ Action onAdError = null,
+ Action onAdClicked = null)
+ {
+ foreach (var adUnitId in adUnitIds)
+ {
+ CreateRewardedAd(adUnitId, onAdLoaded, onAdLoadFailed, onAdShowed, onAdDismissed, onAdError, onAdClicked);
+ }
+ }
+
+ private void CreateRewardedAd(string adUnitId, Action onAdLoaded,
+ Action onAdLoadFailed,
+ Action onAdShowed,
+ Action onAdDismissed,
+ Action onAdError,
+ Action onAdClicked)
+ {
+ if (_interstitialAds.ContainsKey(adUnitId))
+ {
+ LoggerUtils.Debug($"Bigo Interstitial Ad unit {adUnitId} already exists");
+ return;
+ }
+
+ var interstitialAd = new BigoInterstitialAd(adUnitId);
+ _interstitialAds[adUnitId] = interstitialAd;
+ _retryCounters[adUnitId] = 0;
+ _adRevenueCache[adUnitId] = 0;
+
+ interstitialAd.OnLoad += () =>
+ {
+ _retryCounters[adUnitId] = 0;
+ _adRevenueCache[adUnitId] = GetAdRevenue(interstitialAd);
+ LoggerUtils.Debug($"[Bigo] Interstitial -[Load]: {adUnitId} successfully");
+ onAdLoaded?.Invoke(adUnitId);
+ };
+
+ interstitialAd.OnLoadFailed += ((code, msg) =>
+ {
+ _retryCounters[adUnitId]++;
+ double retryDelay = Math.Pow(2, Math.Min(6, _retryCounters[adUnitId]));
+ LoggerUtils.Debug($"[Bigo] Interstitial -[Load]: {adUnitId} failed, errorCode ={code}, error message = {msg}");
+
+ // 延迟重试加载
+ _loadCallbacks[adUnitId] = () => LoadAd(adUnitId);
+ TimerUtils.DelayExecute((float)retryDelay, () => _loadCallbacks[adUnitId]?.Invoke());
+ onAdLoadFailed?.Invoke(adUnitId, code, msg);
+ });
+
+ interstitialAd.OnAdShowed += (() =>
+ {
+ LoggerUtils.Debug($"[Bigo] Interstitial -[interaction]: {adUnitId} show");
+ onAdShowed?.Invoke(adUnitId);
+ });
+
+ interstitialAd.OnAdDismissed += (() =>
+ {
+ LoggerUtils.Debug($"[Bigo] Interstitial -[interaction]: {adUnitId} dismiss");
+ onAdDismissed?.Invoke(adUnitId);
+ });
+
+ interstitialAd.OnAdError += ((code, msg) =>
+ {
+ LoggerUtils.Debug($"[Bigo] Interstitial-[interaction]: {adUnitId} ad error, errorCode ={code}, error message = {msg}");
+ onAdError?.Invoke(adUnitId, code, msg);
+ });
+
+ interstitialAd.OnAdClicked += () =>
+ {
+ onAdClicked?.Invoke();
+ };
+ LoadAd(adUnitId);
+ }
+
+ public void LoadAd(string adUnitId)
+ {
+ if (_interstitialAds.TryGetValue(adUnitId, out var ad))
+ {
+ ad.Load(new BigoInterstitialRequest());
+ }
+ }
+
+ // 显示价格最高的广告
+ public void ShowHighestPayingAd()
+ {
+ var highestPayingAdUnit = GetHighestPayingAdUnit();
+ if (!string.IsNullOrEmpty(highestPayingAdUnit))
+ {
+ ShowAd(highestPayingAdUnit);
+ }
+ }
+
+ // 显示特定广告位的广告
+ private void ShowAd(string adUnitId)
+ {
+ if (_interstitialAds.TryGetValue(adUnitId, out var ad))
+ {
+ ad.Show();
+ }
+ }
+
+
+ // 检查特定广告位是否可用
+ private bool IsAdAvailable(string adUnitId)
+ {
+ return _interstitialAds.TryGetValue(adUnitId, out var ad) && ad.IsLoaded() && !ad.IsExpired();
+ }
+
+ // 获取所有可用的广告位
+ public List GetAvailableAdUnits()
+ {
+ var available = new List();
+ foreach (var kvp in _interstitialAds)
+ {
+ if (kvp.Value.IsLoaded() && !kvp.Value.IsExpired())
+ {
+ available.Add(kvp.Key);
+ }
+ }
+ return available;
+ }
+
+ // 获取广告收益
+ private double GetAdRevenue(BigoInterstitialAd ad)
+ {
+ var bid = ad?.GetBid();
+ if (bid == null) return 0;
+ return bid.getPrice() / 1000;
+ }
+
+ // 获取特定广告位的收益信息
+ 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 = 0;
+
+ foreach (var kvp in _adRevenueCache)
+ {
+ var adUnitId = kvp.Key;
+ var revenue = kvp.Value;
+
+ // 确保广告确实已加载并且价格更高
+ if (IsAdAvailable(adUnitId) && 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 _interstitialAds.Values)
+ {
+ ad.DestroyAd();
+ }
+ _interstitialAds.Clear();
+ _retryCounters.Clear();
+ _loadCallbacks.Clear();
+ _adRevenueCache.Clear();
+ }
+ }
+
+}
+
diff --git a/Assets/Script/SDKManager/AdsSDKManager/BigoAdsManager/BigoInterstitialAdManager.cs.meta b/Assets/Script/SDKManager/AdsSDKManager/BigoAdsManager/BigoInterstitialAdManager.cs.meta
new file mode 100644
index 0000000..edb7674
--- /dev/null
+++ b/Assets/Script/SDKManager/AdsSDKManager/BigoAdsManager/BigoInterstitialAdManager.cs.meta
@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: 5eeffddf05d3b49bfa0c72cb70f6636c
diff --git a/Assets/Script/SDKManager/AdsSDKManager/BigoAdsManager/BigoRewardedAdManager.cs b/Assets/Script/SDKManager/AdsSDKManager/BigoAdsManager/BigoRewardedAdManager.cs
new file mode 100644
index 0000000..e48f5d1
--- /dev/null
+++ b/Assets/Script/SDKManager/AdsSDKManager/BigoAdsManager/BigoRewardedAdManager.cs
@@ -0,0 +1,209 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using BigoAds.Scripts.Api;
+using Script.Utils;
+using UnityEngine;
+
+namespace Script.SDKManager.AdsSDKManager.BigoAdsManager
+{
+
+ public class BigoRewardedAdManager
+ {
+ private Dictionary _rewardedAds = new Dictionary();
+ private Dictionary _retryCounters = new Dictionary();
+ private Dictionary _loadCallbacks = new Dictionary();
+ private Dictionary _adRevenueCache = new Dictionary();
+
+ public void InitializeAdUnits(List adUnitIds, Action onAdLoaded = null,
+ Action onAdLoadFailed = null,
+ Action onAdShowed = null,
+ Action onAdDismissed = null,
+ Action onAdError = null,
+ Action onAdClicked = null)
+ {
+ foreach (var adUnitId in adUnitIds)
+ {
+ CreateRewardedAd(adUnitId, onAdLoaded, onAdLoadFailed, onAdShowed, onAdDismissed, onAdError, onAdClicked);
+ }
+ }
+
+ private void CreateRewardedAd(string adUnitId, Action onAdLoaded,
+ Action onAdLoadFailed,
+ Action onAdShowed,
+ Action onAdDismissed,
+ Action onAdError,
+ Action onAdClicked)
+ {
+ if (_rewardedAds.ContainsKey(adUnitId))
+ {
+ Debug.LogWarning($"Ad unit {adUnitId} already exists");
+ return;
+ }
+
+ var rewardedAd = new BigoRewardedAd(adUnitId);
+ _rewardedAds[adUnitId] = rewardedAd;
+ _retryCounters[adUnitId] = 0;
+ _adRevenueCache[adUnitId] = 0;
+
+ rewardedAd.OnLoad += () =>
+ {
+ _retryCounters[adUnitId] = 0;
+ _adRevenueCache[adUnitId] = GetAdRevenue(rewardedAd);
+ LoggerUtils.Debug($"[BigoRewarded]-[Load]: {adUnitId} successfully");
+ onAdLoaded?.Invoke(adUnitId);
+ };
+
+ rewardedAd.OnLoadFailed += ((code, msg) =>
+ {
+ _retryCounters[adUnitId]++;
+ double retryDelay = Math.Pow(2, Math.Min(6, _retryCounters[adUnitId]));
+ LoggerUtils.Debug($"[BigoRewarded]-[Load]: {adUnitId} failed, errorCode ={code}, error message = {msg}");
+
+ // 延迟重试加载
+ _loadCallbacks[adUnitId] = () => LoadAd(adUnitId);
+ TimerUtils.DelayExecute((float)retryDelay, () => _loadCallbacks[adUnitId]?.Invoke());
+ onAdLoadFailed?.Invoke(adUnitId, code, msg);
+ });
+
+ rewardedAd.OnAdShowed += (() =>
+ {
+ LoggerUtils.Debug($"[BigoRewarded]-[interaction]: {adUnitId} show");
+ onAdShowed?.Invoke(adUnitId);
+ });
+
+ rewardedAd.OnAdDismissed += (() =>
+ {
+ LoggerUtils.Debug($"[BigoRewarded]-[interaction]: {adUnitId} dismiss");
+ onAdDismissed?.Invoke(adUnitId);
+ });
+
+ rewardedAd.OnAdError += ((code, msg) =>
+ {
+ LoggerUtils.Debug($"[BigoRewarded]-[interaction]: {adUnitId} ad error, errorCode ={code}, error message = {msg}");
+ onAdError?.Invoke(adUnitId, code, msg);
+ });
+
+ rewardedAd.OnAdClicked += () =>
+ {
+ onAdClicked?.Invoke();
+ };
+ LoadAd(adUnitId);
+ }
+
+ public void LoadAd(string adUnitId)
+ {
+ if (_rewardedAds.TryGetValue(adUnitId, out var ad))
+ {
+ ad.Load(new BigoRewardedRequest());
+ }
+ }
+
+ // 显示价格最高的广告
+ public void ShowHighestPayingAd()
+ {
+ var highestPayingAdUnit = GetHighestPayingAdUnit();
+ if (!string.IsNullOrEmpty(highestPayingAdUnit))
+ {
+ ShowAd(highestPayingAdUnit);
+ }
+ }
+
+ // 显示特定广告位的广告
+ private void ShowAd(string adUnitId)
+ {
+ if (_rewardedAds.TryGetValue(adUnitId, out var ad))
+ {
+ ad.Show();
+ }
+ }
+
+
+ // 检查特定广告位是否可用
+ private bool IsAdAvailable(string adUnitId)
+ {
+ return _rewardedAds.TryGetValue(adUnitId, out var ad) && ad.IsLoaded() && !ad.IsExpired();
+ }
+
+ // 获取所有可用的广告位
+ public List GetAvailableAdUnits()
+ {
+ var available = new List();
+ foreach (var kvp in _rewardedAds)
+ {
+ if (kvp.Value.IsLoaded() && !kvp.Value.IsExpired())
+ {
+ available.Add(kvp.Key);
+ }
+ }
+ return available;
+ }
+
+ // 获取广告收益
+ private double GetAdRevenue(BigoRewardedAd ad)
+ {
+ var bid = ad?.GetBid();
+ if (bid == null) return 0;
+ return bid.getPrice() / 1000;
+ }
+
+ // 获取特定广告位的收益信息
+ 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 = 0;
+
+ foreach (var kvp in _adRevenueCache)
+ {
+ var adUnitId = kvp.Key;
+ var revenue = kvp.Value;
+
+ // 确保广告确实已加载并且价格更高
+ if (IsAdAvailable(adUnitId) && 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 _rewardedAds.Values)
+ {
+ ad.DestroyAd();
+ }
+ _rewardedAds.Clear();
+ _retryCounters.Clear();
+ _loadCallbacks.Clear();
+ _adRevenueCache.Clear();
+ }
+ }
+
+}
+
diff --git a/Assets/Script/SDKManager/AdsSDKManager/BigoAdsManager/BigoRewardedAdManager.cs.meta b/Assets/Script/SDKManager/AdsSDKManager/BigoAdsManager/BigoRewardedAdManager.cs.meta
new file mode 100644
index 0000000..af78faf
--- /dev/null
+++ b/Assets/Script/SDKManager/AdsSDKManager/BigoAdsManager/BigoRewardedAdManager.cs.meta
@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: c2a850afd5e804d71a3bda35898ee218
\ No newline at end of file
diff --git a/Assets/Script/Utils.meta b/Assets/Script/Utils.meta
new file mode 100644
index 0000000..4e40a32
--- /dev/null
+++ b/Assets/Script/Utils.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: f3dcbc43a8b6e4fe1a9fc9170c244785
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Script/Utils/LoggerUtils.cs b/Assets/Script/Utils/LoggerUtils.cs
new file mode 100644
index 0000000..b715804
--- /dev/null
+++ b/Assets/Script/Utils/LoggerUtils.cs
@@ -0,0 +1,55 @@
+using System.Collections;
+using System.Collections.Generic;
+using Unity.VisualScripting;
+using UnityEngine;
+
+namespace Script.Utils
+{
+ public static class LoggerUtils
+ {
+ private static bool _enabled = true;
+
+ public static bool Enabled
+ {
+ get => _enabled;
+ set => _enabled = value;
+ }
+
+ public static void Debug(object message, Object context = null)
+ {
+ if (!_enabled) return;
+ Log($"[DEBUG] {message}", context);
+ }
+
+ public static void Info(object message, Object context = null)
+ {
+ if (!!_enabled) return;
+ Log($"[INFO] {message}", context);
+ }
+
+ public static void Warning(object message, Object context = null)
+ {
+ if (!_enabled) return;
+ Log($"[WARNING] {message}", context);
+ }
+
+ public static void Error(object message, Object context = null)
+ {
+ if (!!_enabled) return;
+ Log($"[ERROR] {message}", context);
+ }
+
+ private static void Log(string message, Object context = null)
+ {
+ if (context != null)
+ {
+ UnityEngine.Debug.Log(message, context);
+ }
+ else
+ {
+ UnityEngine.Debug.Log(message);
+ }
+ }
+ }
+}
+
diff --git a/Assets/Script/Utils/LoggerUtils.cs.meta b/Assets/Script/Utils/LoggerUtils.cs.meta
new file mode 100644
index 0000000..1fe5299
--- /dev/null
+++ b/Assets/Script/Utils/LoggerUtils.cs.meta
@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: 7e6c7794484654e39acf594e7200206a
\ No newline at end of file
diff --git a/Assets/Script/Utils/SingletonBase.cs b/Assets/Script/Utils/SingletonBase.cs
new file mode 100644
index 0000000..11847b6
--- /dev/null
+++ b/Assets/Script/Utils/SingletonBase.cs
@@ -0,0 +1,165 @@
+using UnityEngine;
+
+namespace SDK.Utils
+{
+ public abstract class NormalSingleton where T : new()
+ {
+ private static T mInstance;
+ public static T Instance
+ {
+ get
+ {
+ if (mInstance == null)
+ {
+ mInstance = new T();
+ }
+
+ return mInstance;
+ }
+ }
+ }
+
+ ///
+ /// 动态(Dynamic)
+ ///
+ public abstract class D_MonoSingleton : MonoBehaviour where T : D_MonoSingleton
+ {
+ private static T mInstance = null;
+
+ public static T Instance
+ {
+ get
+ {
+ if (mInstance == null)
+ {
+ GameObject tFramewokGo = GameObject.Find("TKFramework");
+ if (tFramewokGo == null)
+ {
+ tFramewokGo = new GameObject("TKFramework");
+ DontDestroyOnLoad(tFramewokGo);
+ }
+ GameObject tGo = new GameObject();
+ tGo.transform.SetParent(tFramewokGo.transform);
+ tGo.name = typeof(T).ToString();
+ tGo.transform.localPosition = Vector3.zero;
+ tGo.transform.localEulerAngles = Vector3.zero;
+ tGo.transform.localScale = Vector3.one;
+ mInstance = tGo.AddComponent();
+ }
+ return mInstance;
+ }
+ }
+
+ protected Transform mTrans;
+
+ private void Awake()
+ {
+ mTrans = transform;
+ Initialize();
+ }
+
+ protected virtual void Initialize()
+ {
+
+ }
+
+ private void OnDestroy()
+ {
+ mInstance = null;
+
+ Dispose();
+ }
+
+ protected virtual void Dispose()
+ {
+
+ }
+ }
+
+ ///
+ /// 静态(static)
+ ///
+ public abstract class S_MonoSingleton : MonoBehaviour where T : S_MonoSingleton
+ {
+ private static T mInstance = null;
+ public static T Instance
+ {
+ get
+ {
+ return mInstance;
+ }
+ }
+
+ private void Awake()
+ {
+ if (mInstance != null && mInstance != (T)this)
+ {
+ Destroy(gameObject);
+ return;
+ }
+ mInstance = (T)this;
+ Initialize();
+ }
+
+ protected virtual void Initialize()
+ {
+
+ }
+
+ private void OnDestroy()
+ {
+ mInstance = null;
+
+ Dispose();
+ }
+
+ protected virtual void Dispose()
+ {
+
+ }
+ }
+
+ ///
+ /// 静态常驻
+ ///
+ public abstract class O_MonoSingleton : MonoBehaviour where T : O_MonoSingleton
+ {
+ private static T mInstance = null;
+ public static T Instance
+ {
+ get
+ {
+ return mInstance;
+ }
+ }
+
+ private void Awake()
+ {
+ if (mInstance != null && mInstance != (T)this)
+ {
+ Destroy(gameObject);
+ return;
+ }
+ mInstance = (T)this;
+ DontDestroyOnLoad(gameObject);
+ Initialize();
+ }
+
+ protected virtual void Initialize()
+ {
+
+ }
+
+ private void OnDestroy()
+ {
+ mInstance = null;
+
+ Dispose();
+ }
+
+ protected virtual void Dispose()
+ {
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/Script/Utils/SingletonBase.cs.meta b/Assets/Script/Utils/SingletonBase.cs.meta
new file mode 100644
index 0000000..78681d5
--- /dev/null
+++ b/Assets/Script/Utils/SingletonBase.cs.meta
@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: eb54f82607e0946e4ac5cbfb0ca49967
\ No newline at end of file
diff --git a/Assets/Script/Utils/TimerUtils.cs b/Assets/Script/Utils/TimerUtils.cs
new file mode 100644
index 0000000..0aa1dcb
--- /dev/null
+++ b/Assets/Script/Utils/TimerUtils.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace Script.Utils
+{
+ public static class TimerUtils
+ {
+ private static MonoBehaviour _coroutineRunner;
+
+ public static void Initialize(MonoBehaviour runner)
+ {
+ _coroutineRunner = runner;
+ }
+
+ public static void DelayExecute(float delay, Action action)
+ {
+ if (_coroutineRunner != null)
+ {
+ _coroutineRunner.StartCoroutine(DelayExecuteCoroutine(delay, action));
+ }
+ }
+
+ private static IEnumerator DelayExecuteCoroutine(float delay, Action action)
+ {
+ yield return new WaitForSeconds(delay);
+ action?.Invoke();
+ }
+ }
+
+}
+
diff --git a/Assets/Script/Utils/TimerUtils.cs.meta b/Assets/Script/Utils/TimerUtils.cs.meta
new file mode 100644
index 0000000..a7a8229
--- /dev/null
+++ b/Assets/Script/Utils/TimerUtils.cs.meta
@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: 6e18cf88978e94ad4bd074b3a427bbc9
\ No newline at end of file