From 18af360571ee2c49db871691cd6f4acc15c0569f Mon Sep 17 00:00:00 2001 From: CORE-FOLDCCCore <1813547935@qq.com> Date: Wed, 17 Jun 2026 15:40:25 +0800 Subject: [PATCH] release: 1.0.4 --- CHANGELOG.md | 12 + .../Runtime/Scripts/TapadnAwardVideoPlayer.cs | 220 +++++++++++++++--- .../Scripts/TapadnCommercialization.cs | 28 +++ .../Scripts/TapadnControllerOptions.cs | 136 +++++++++++ .../Scripts/TapadnInteractionPlayer.cs | 17 +- .../Scripts/TapadnSmartLoadOrchestrator.cs | 92 ++++---- .../Runtime/Scripts/TapadnSplashPlayer.cs | 17 +- package.json | 2 +- 8 files changed, 432 insertions(+), 92 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c9bed4..627889b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +# [1.0.4] + +### 新增 + +* 激励视频支持按游戏场景映射不同 TapADN SpaceId,并在未配置或配置非法时回退默认激励广告位。 +* 手动加载模式下激励视频缓存按 SpaceId 隔离,避免不同场景广告位串用 ready 缓存。 +* 激励视频缓存默认 10 分钟未消费自动销毁,可通过 `tapadn.rewarded_cache_max_age_seconds` 覆盖。 + +### 调整 + +* 智能预加载归因缓存增加 SpaceId 维度,避免多广告位场景下 ready/归因状态混用。 + # [1.0.3] ### 修复 diff --git a/Tapadn_Adapter/Runtime/Scripts/TapadnAwardVideoPlayer.cs b/Tapadn_Adapter/Runtime/Scripts/TapadnAwardVideoPlayer.cs index 20183aa..7e986c9 100644 --- a/Tapadn_Adapter/Runtime/Scripts/TapadnAwardVideoPlayer.cs +++ b/Tapadn_Adapter/Runtime/Scripts/TapadnAwardVideoPlayer.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using Dirichlet.Mediation; using Runtime.ADAggregator; using UnityEngine; @@ -7,8 +8,11 @@ public sealed class TapadnAwardVideoPlayer : ADPlayer, IDirichletRewardVideoAuto { private const float RewardCloseSettleDelaySeconds = 0.25f; + private readonly Dictionary _slotCaches = new Dictionary(StringComparer.Ordinal); + private DirichletAdNative _adNative; - private DirichletRewardVideoAd _loadedAd; + private string _defaultSlotId; + private string _activeSlotId; private bool _rewardVerified; private bool _rewardVerifyReceived; private bool _closePendingRewardVerify; @@ -22,30 +26,46 @@ public sealed class TapadnAwardVideoPlayer : ADPlayer, IDirichletRewardVideoAuto public override void OnInit() { + _defaultSlotId = Key; _adNative = DirichletAdManager.CreateAdNative(); } public override bool IsReadly() { + var slotId = ResolveCurrentSlotId(); if (UseAutoLoad()) { - return TapadnAdRequestFactory.TryParseSlotId(Key, out _); + return TapadnAdRequestFactory.TryParseSlotId(slotId, out _); } - if (_loadedAd != null && _loadedAd.IsLoaded && _loadedAd.IsValid) + var cache = GetCache(slotId); + if (IsCacheReady(cache)) { curState = 2; return true; } + if (cache != null && cache.Loading) + { + curState = 1; + return false; + } + + if (cache != null) + { + RemoveCache(slotId); + } + + curState = 0; return false; } public override void LoadAD() { - if (!TapadnAdRequestFactory.TryParseSlotId(Key, out _)) + var slotId = ResolveCurrentSlotId(); + if (!TapadnAdRequestFactory.TryParseSlotId(slotId, out _)) { - Debug.LogError($"[TapADN] Invalid rewarded slot id: {Key}"); + Debug.LogError($"[TapADN] Invalid rewarded slot id: {slotId}"); curState = 0; return; } @@ -55,7 +75,7 @@ public sealed class TapadnAwardVideoPlayer : ADPlayer, IDirichletRewardVideoAuto curState = 2; try { - _adNative.PreLoad(TapadnAdRequestFactory.BuildRewarded(Key, TapadnAdController.CurrentOptions), 3); + _adNative.PreLoad(TapadnAdRequestFactory.BuildRewarded(slotId, TapadnAdController.CurrentOptions), 3); } catch (Exception exception) { @@ -64,33 +84,37 @@ public sealed class TapadnAwardVideoPlayer : ADPlayer, IDirichletRewardVideoAuto return; } - if (curState == 1 || IsReadly()) + var cache = GetCache(slotId); + if (cache != null && (cache.Loading || IsCacheReady(cache))) { + curState = cache.Loading ? 1 : 2; return; } + cache = new RewardedSlotCache { Loading = true }; + _slotCaches[slotId] = cache; curState = 1; - TapadnSmartLoadOrchestrator.OnLoadStarted(AD_Type.AwardVideo, AdScene); + TapadnSmartLoadOrchestrator.OnLoadStarted(AD_Type.AwardVideo, AdScene, slotId); _adNative.LoadRewardVideoAd( - TapadnAdRequestFactory.BuildRewarded(Key, TapadnAdController.CurrentOptions), + TapadnAdRequestFactory.BuildRewarded(slotId, TapadnAdController.CurrentOptions), ad => { - TapadnSmartLoadOrchestrator.OnLoadResult(AD_Type.AwardVideo, AdScene, true); - _loadedAd?.Destroy(); - _loadedAd = ad; - _loadedAd.Shown += OnManualShown; - _loadedAd.Clicked += OnManualClicked; - _loadedAd.ShowFailed += OnManualShowFailed; - _loadedAd.RewardVerified += OnManualRewardVerify; - _loadedAd.Closed += OnManualClosed; - curState = 2; - Debug.Log($"[TapADN] Rewarded loaded. slot={Key}"); + TapadnSmartLoadOrchestrator.OnLoadResult(AD_Type.AwardVideo, AdScene, true, slotId); + DestroyCachedAd(cache); + cache.Ad = ad; + cache.Loading = false; + cache.LoadedUnix = GetNowUnixSeconds(); + RegisterManualEvents(slotId, cache.Ad); + ScheduleCacheExpiration(slotId, cache); + curState = string.Equals(slotId, ResolveCurrentSlotId(), StringComparison.Ordinal) ? 2 : curState; + Debug.Log($"[TapADN] Rewarded loaded. scene={NormalizeScenario(AdScene)}, slot={slotId}"); }, error => { - TapadnSmartLoadOrchestrator.OnLoadResult(AD_Type.AwardVideo, AdScene, false); - curState = 0; - Debug.LogError($"[TapADN] Rewarded load failed. code={error.Code}, message={error.Message}"); + TapadnSmartLoadOrchestrator.OnLoadResult(AD_Type.AwardVideo, AdScene, false, slotId); + RemoveCache(slotId); + curState = string.Equals(slotId, ResolveCurrentSlotId(), StringComparison.Ordinal) ? 0 : curState; + Debug.LogError($"[TapADN] Rewarded load failed. slot={slotId}, code={error.Code}, message={error.Message}"); }); } @@ -104,16 +128,20 @@ public sealed class TapadnAwardVideoPlayer : ADPlayer, IDirichletRewardVideoAuto _showSettled = false; _rewardCloseSettleHandler?.Kill(); _rewardCloseSettleHandler = null; + _activeSlotId = ResolveCurrentSlotId(); + Key = _activeSlotId; curState = 0; if (UseAutoLoad()) { - _adNative.ShowRewardVideoAutoAd(TapadnAdRequestFactory.BuildRewarded(Key, TapadnAdController.CurrentOptions), this); + _adNative.ShowRewardVideoAutoAd(TapadnAdRequestFactory.BuildRewarded(_activeSlotId, TapadnAdController.CurrentOptions), this); return; } - if (_loadedAd == null || !_loadedAd.Show()) + var cache = GetCache(_activeSlotId); + if (!IsCacheReady(cache) || cache.Ad == null || !cache.Ad.Show()) { + RemoveCache(_activeSlotId); OnError(new DirichletError("show_failed", "ShowRewardVideoAd returned false")); return; } @@ -130,14 +158,14 @@ public sealed class TapadnAwardVideoPlayer : ADPlayer, IDirichletRewardVideoAuto _rewardCloseSettleHandler?.Kill(); _rewardCloseSettleHandler = null; curState = 0; - TapadnSmartLoadOrchestrator.OnShowError(AD_Type.AwardVideo, AdScene); - Debug.LogError($"[TapADN] Rewarded show failed. code={error?.Code}, message={error?.Message}"); + TapadnSmartLoadOrchestrator.OnShowError(AD_Type.AwardVideo, AdScene, _activeSlotId); + Debug.LogError($"[TapADN] Rewarded show failed. slot={_activeSlotId}, code={error?.Code}, message={error?.Message}"); adListener.OnShowError(); } public void OnAdShow() { - TapadnSmartLoadOrchestrator.OnShowStart(AD_Type.AwardVideo, AdScene); + TapadnSmartLoadOrchestrator.OnShowStart(AD_Type.AwardVideo, AdScene, _activeSlotId); NotifyShowStarted(); } @@ -175,12 +203,23 @@ public sealed class TapadnAwardVideoPlayer : ADPlayer, IDirichletRewardVideoAuto public override void OnPlayRequestStarted() { - TapadnSmartLoadOrchestrator.OnPlayRequestStarted(AD_Type.AwardVideo, AdScene, !UseAutoLoad() && IsReadly()); + var slotId = ResolveCurrentSlotId(); + Key = slotId; + TapadnSmartLoadOrchestrator.OnPlayRequestStarted(AD_Type.AwardVideo, AdScene, !UseAutoLoad() && IsReadly(), slotId); } public override void EnterAdScenario(string scenario) { - TapadnSmartLoadOrchestrator.OnEnterAdScenario(AD_Type.AwardVideo, scenario, Key); + AdScene = NormalizeScenario(scenario); + var slotId = ResolveCurrentSlotId(); + Key = slotId; + TapadnSmartLoadOrchestrator.OnEnterAdScenario(AD_Type.AwardVideo, AdScene, slotId); + } + + private string ResolveCurrentSlotId() + { + var slotId = TapadnAdController.CurrentOptions?.ResolveRewardedSlotId(_defaultSlotId, AdScene) ?? _defaultSlotId; + return string.IsNullOrWhiteSpace(slotId) ? _defaultSlotId : slotId.Trim(); } private bool UseAutoLoad() @@ -188,8 +227,66 @@ public sealed class TapadnAwardVideoPlayer : ADPlayer, IDirichletRewardVideoAuto return TapadnAdController.CurrentOptions?.RewardedAutoLoad ?? true; } - private void OnManualShown() + private RewardedSlotCache GetCache(string slotId) { + return !string.IsNullOrWhiteSpace(slotId) && _slotCaches.TryGetValue(slotId, out var cache) ? cache : null; + } + + private bool IsCacheReady(RewardedSlotCache cache) + { + if (cache == null || cache.Loading || cache.Ad == null || !cache.Ad.IsLoaded || !cache.Ad.IsValid) + { + return false; + } + + var maxAgeSeconds = TapadnAdController.CurrentOptions?.RewardedCacheMaxAgeSeconds ?? 0; + return maxAgeSeconds <= 0 || GetNowUnixSeconds() - cache.LoadedUnix <= maxAgeSeconds; + } + + private void RegisterManualEvents(string slotId, DirichletRewardVideoAd ad) + { + if (ad == null) + { + return; + } + + ad.Shown += () => OnManualShown(slotId); + ad.Clicked += OnManualClicked; + ad.ShowFailed += error => OnManualShowFailed(slotId, error); + ad.RewardVerified += OnManualRewardVerify; + ad.Closed += () => OnManualClosed(slotId); + } + + private void ScheduleCacheExpiration(string slotId, RewardedSlotCache cache) + { + cache.ExpireHandler?.Kill(); + cache.ExpireHandler = null; + + var maxAgeSeconds = TapadnAdController.CurrentOptions?.RewardedCacheMaxAgeSeconds ?? 600; + if (maxAgeSeconds <= 0) + { + return; + } + + cache.ExpireHandler = ADManager.Instance.CreateTimer(maxAgeSeconds, () => + { + if (!ReferenceEquals(GetCache(slotId), cache)) + { + return; + } + + Debug.Log($"[TapADN] Rewarded cache expired. slot={slotId}, maxAgeSeconds={maxAgeSeconds}"); + RemoveCache(slotId); + if (string.Equals(slotId, ResolveCurrentSlotId(), StringComparison.Ordinal)) + { + curState = 0; + } + }); + } + + private void OnManualShown(string slotId) + { + _activeSlotId = slotId; OnAdShow(); } @@ -197,8 +294,9 @@ public sealed class TapadnAwardVideoPlayer : ADPlayer, IDirichletRewardVideoAuto { } - private void OnManualShowFailed(DirichletError error) + private void OnManualShowFailed(string slotId, DirichletError error) { + RemoveCache(slotId); OnError(error); } @@ -207,13 +305,49 @@ public sealed class TapadnAwardVideoPlayer : ADPlayer, IDirichletRewardVideoAuto OnRewardVerify(args); } - private void OnManualClosed() + private void OnManualClosed(string slotId) { - _loadedAd?.Destroy(); - _loadedAd = null; + RemoveCache(slotId); OnAdClose(); } + private void RemoveCache(string slotId) + { + var cache = GetCache(slotId); + if (cache == null) + { + return; + } + + DestroyCachedAd(cache); + _slotCaches.Remove(slotId); + } + + private static void DestroyCachedAd(RewardedSlotCache cache) + { + if (cache?.Ad == null) + { + return; + } + + try + { + cache.ExpireHandler?.Kill(); + cache.ExpireHandler = null; + cache.Ad.Destroy(); + } + catch (Exception exception) + { + Debug.LogWarning($"[TapADN] Rewarded Destroy failed: {exception.Message}"); + } + finally + { + cache.Ad = null; + cache.Loading = false; + cache.LoadedUnix = 0; + } + } + private void CompleteRewardedClose() { if (_showSettled) @@ -228,4 +362,22 @@ public sealed class TapadnAwardVideoPlayer : ADPlayer, IDirichletRewardVideoAuto adListener.OnRewardVerify(_rewardVerified, TapadnAdController.CurrentOptions?.RewardAmount ?? 1, TapadnAdController.CurrentOptions?.RewardName ?? string.Empty); adListener.OnAdClose(); } + + private static string NormalizeScenario(string scenario) + { + return string.IsNullOrWhiteSpace(scenario) ? "__default__" : scenario.Trim(); + } + + private static long GetNowUnixSeconds() + { + return (long)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds; + } + + private sealed class RewardedSlotCache + { + public DirichletRewardVideoAd Ad; + public bool Loading; + public long LoadedUnix; + public AdTimeHandler ExpireHandler; + } } diff --git a/Tapadn_Adapter/Runtime/Scripts/TapadnCommercialization.cs b/Tapadn_Adapter/Runtime/Scripts/TapadnCommercialization.cs index bfc1a0c..42bd8ef 100644 --- a/Tapadn_Adapter/Runtime/Scripts/TapadnCommercialization.cs +++ b/Tapadn_Adapter/Runtime/Scripts/TapadnCommercialization.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using Runtime.ADAggregator; public static class TapadnCommercialization @@ -31,4 +32,31 @@ public static class TapadnCommercialization config.BaseSplashAdKeyValue = new AdKeyValue { key = "splash", value = splashSlotId }; return config; } + + public static void SetRewardedSceneSlots(ADConfig config, IDictionary sceneSlotIds) + { + if (config == null || sceneSlotIds == null || sceneSlotIds.Count == 0) + { + return; + } + + if (config.CommonKeyValues == null) + { + config.CommonKeyValues = new List(); + } + + foreach (var entry in sceneSlotIds) + { + if (string.IsNullOrWhiteSpace(entry.Key) || string.IsNullOrWhiteSpace(entry.Value)) + { + continue; + } + + config.CommonKeyValues.Add(new AdKeyValue + { + key = TapadnControllerOptions.RewardedSceneSlotPrefix + entry.Key.Trim(), + value = entry.Value.Trim() + }); + } + } } diff --git a/Tapadn_Adapter/Runtime/Scripts/TapadnControllerOptions.cs b/Tapadn_Adapter/Runtime/Scripts/TapadnControllerOptions.cs index 0534b44..7bd488c 100644 --- a/Tapadn_Adapter/Runtime/Scripts/TapadnControllerOptions.cs +++ b/Tapadn_Adapter/Runtime/Scripts/TapadnControllerOptions.cs @@ -27,6 +27,10 @@ public sealed class TapadnControllerOptions public const string RewardedMaxLoadAttemptsKey = "tapadn.rewarded_max_load_attempts"; public const string RewardedLoadRetryDelayMsKey = "tapadn.rewarded_load_retry_delay_ms"; public const string RewardedShowTimeoutMsKey = "tapadn.rewarded_show_timeout_ms"; + public const string RewardedSceneSlotPrefix = "tapadn.rewarded_scene_slot."; + public const string RewardedSceneSlotsKey = "tapadn.rewarded_scene_slots"; + public const string RewardedSceneSlotsJsonKey = "tapadn.rewarded_scene_slots_json"; + public const string RewardedCacheMaxAgeSecondsKey = "tapadn.rewarded_cache_max_age_seconds"; public const string RewardNameKey = "tapadn.reward_name"; public const string RewardAmountKey = "tapadn.reward_amount"; public const string InterstitialAutoLoadKey = "tapadn.interstitial_auto_load"; @@ -64,6 +68,8 @@ public sealed class TapadnControllerOptions public int RewardedMaxLoadAttempts { get; set; } = 1; public int RewardedLoadRetryDelayMs { get; set; } = 500; public int RewardedShowTimeoutMs { get; set; } = 20000; + public int RewardedCacheMaxAgeSeconds { get; set; } = 600; + public Dictionary RewardedSceneSlotIds { get; private set; } = new Dictionary(StringComparer.Ordinal); public string RewardName { get; set; } = "reward"; public int RewardAmount { get; set; } = 1; public bool InterstitialAutoLoad { get; set; } = false; @@ -205,6 +211,11 @@ public sealed class TapadnControllerOptions RewardedMaxLoadAttempts = incoming.RewardedMaxLoadAttempts; RewardedLoadRetryDelayMs = incoming.RewardedLoadRetryDelayMs; RewardedShowTimeoutMs = incoming.RewardedShowTimeoutMs; + RewardedCacheMaxAgeSeconds = incoming.RewardedCacheMaxAgeSeconds; + if (incoming.RewardedSceneSlotIds != null && incoming.RewardedSceneSlotIds.Count > 0) + { + RewardedSceneSlotIds = CloneSceneSlotMap(incoming.RewardedSceneSlotIds); + } RewardName = incoming.RewardName ?? RewardName; RewardAmount = incoming.RewardAmount; InterstitialAutoLoad = incoming.InterstitialAutoLoad; @@ -266,6 +277,8 @@ public sealed class TapadnControllerOptions RewardedMaxLoadAttempts = GetInt(map, RewardedMaxLoadAttemptsKey) ?? RewardedMaxLoadAttempts; RewardedLoadRetryDelayMs = GetInt(map, RewardedLoadRetryDelayMsKey) ?? RewardedLoadRetryDelayMs; RewardedShowTimeoutMs = GetInt(map, RewardedShowTimeoutMsKey) ?? RewardedShowTimeoutMs; + RewardedCacheMaxAgeSeconds = Math.Max(0, GetInt(map, RewardedCacheMaxAgeSecondsKey) ?? RewardedCacheMaxAgeSeconds); + ApplyRewardedSceneSlots(map); RewardName = GetString(map, RewardNameKey) ?? RewardName; RewardAmount = GetInt(map, RewardAmountKey) ?? RewardAmount; InterstitialAutoLoad = GetBool(map, InterstitialAutoLoadKey) ?? InterstitialAutoLoad; @@ -286,6 +299,116 @@ public sealed class TapadnControllerOptions ExpressHeight = GetInt(map, ExpressHeightKey) ?? ExpressHeight; } + public string ResolveRewardedSlotId(string defaultSlotId, string scenario) + { + var normalizedScenario = NormalizeScenario(scenario); + if (RewardedSceneSlotIds != null && + RewardedSceneSlotIds.TryGetValue(normalizedScenario, out var mappedSlotId) && + TapadnAdRequestFactory.TryParseSlotId(mappedSlotId, out _)) + { + return mappedSlotId; + } + + return defaultSlotId; + } + + private void ApplyRewardedSceneSlots(IDictionary map) + { + foreach (var entry in map) + { + if (entry.Key == null || !entry.Key.StartsWith(RewardedSceneSlotPrefix, StringComparison.OrdinalIgnoreCase)) + { + continue; + } + + var scene = entry.Key.Substring(RewardedSceneSlotPrefix.Length); + AddRewardedSceneSlot(scene, entry.Value); + } + + ParseSceneSlotPairs(GetString(map, RewardedSceneSlotsKey), AddRewardedSceneSlot); + ParseSceneSlotJson(GetString(map, RewardedSceneSlotsJsonKey), AddRewardedSceneSlot); + } + + private void AddRewardedSceneSlot(string scene, string slotId) + { + scene = NormalizeScenario(scene); + if (string.IsNullOrWhiteSpace(slotId) || !TapadnAdRequestFactory.TryParseSlotId(slotId.Trim(), out _)) + { + UnityEngine.Debug.LogWarning($"[TapADN] Ignore invalid rewarded scene slot. scene={scene}, slot={slotId}"); + return; + } + + RewardedSceneSlotIds[scene] = slotId.Trim(); + } + + private static void ParseSceneSlotPairs(string value, Action add) + { + if (string.IsNullOrWhiteSpace(value) || add == null) + { + return; + } + + var pairs = value.Split(new[] { ',', ';', '\n', '\r', '|' }, StringSplitOptions.RemoveEmptyEntries); + foreach (var pair in pairs) + { + var separatorIndex = pair.IndexOf('='); + if (separatorIndex < 0) + { + separatorIndex = pair.IndexOf(':'); + } + + if (separatorIndex <= 0 || separatorIndex >= pair.Length - 1) + { + continue; + } + + add(pair.Substring(0, separatorIndex), pair.Substring(separatorIndex + 1)); + } + } + + private static void ParseSceneSlotJson(string json, Action add) + { + if (string.IsNullOrWhiteSpace(json) || add == null) + { + return; + } + + try + { + var parsed = JsonUtility.FromJson(json); + if (parsed?.Mappings == null) + { + return; + } + + foreach (var mapping in parsed.Mappings) + { + if (mapping == null) + { + continue; + } + + add(mapping.Scene, mapping.SlotId); + } + } + catch (Exception exception) + { + UnityEngine.Debug.LogWarning($"[TapADN] Parse rewarded scene slot JSON failed: {exception.Message}"); + } + } + + private static Dictionary CloneSceneSlotMap(Dictionary source) + { + return source == null + ? new Dictionary(StringComparer.Ordinal) + : new Dictionary(source, StringComparer.Ordinal); + } + + private static string NormalizeScenario(string scenario) + { + return string.IsNullOrWhiteSpace(scenario) ? "__default__" : scenario.Trim(); + } + private static string GetString(IDictionary map, params string[] keys) { foreach (var key in keys) @@ -383,4 +506,17 @@ public sealed class TapadnControllerOptions return value.ToString(); } + + [Serializable] + private sealed class TapadnSceneSlotMapConfig + { + public List Mappings; + } + + [Serializable] + private sealed class TapadnSceneSlotMapping + { + public string Scene; + public string SlotId; + } } diff --git a/Tapadn_Adapter/Runtime/Scripts/TapadnInteractionPlayer.cs b/Tapadn_Adapter/Runtime/Scripts/TapadnInteractionPlayer.cs index 1d516c0..aafd9c3 100644 --- a/Tapadn_Adapter/Runtime/Scripts/TapadnInteractionPlayer.cs +++ b/Tapadn_Adapter/Runtime/Scripts/TapadnInteractionPlayer.cs @@ -56,12 +56,12 @@ public sealed class TapadnInteractionPlayer : ADPlayer, IDirichletInterstitialAu } curState = 1; - TapadnSmartLoadOrchestrator.OnLoadStarted(AD_Type.Interaction, AdScene); + TapadnSmartLoadOrchestrator.OnLoadStarted(AD_Type.Interaction, AdScene, Key); _adNative.LoadInterstitialAd( TapadnAdRequestFactory.BuildInterstitial(Key, TapadnAdController.CurrentOptions), ad => { - TapadnSmartLoadOrchestrator.OnLoadResult(AD_Type.Interaction, AdScene, true); + TapadnSmartLoadOrchestrator.OnLoadResult(AD_Type.Interaction, AdScene, true, Key); _loadedAd?.Destroy(); _loadedAd = ad; _loadedAd.Shown += OnManualShown; @@ -73,7 +73,7 @@ public sealed class TapadnInteractionPlayer : ADPlayer, IDirichletInterstitialAu }, error => { - TapadnSmartLoadOrchestrator.OnLoadResult(AD_Type.Interaction, AdScene, false); + TapadnSmartLoadOrchestrator.OnLoadResult(AD_Type.Interaction, AdScene, false, Key); curState = 0; Debug.LogError($"[TapADN] Interstitial load failed. code={error.Code}, message={error.Message}"); }); @@ -106,7 +106,7 @@ public sealed class TapadnInteractionPlayer : ADPlayer, IDirichletInterstitialAu } _showSettled = true; - TapadnSmartLoadOrchestrator.OnShowError(AD_Type.Interaction, AdScene); + TapadnSmartLoadOrchestrator.OnShowError(AD_Type.Interaction, AdScene, Key); curState = 0; Debug.LogError($"[TapADN] Interstitial show failed. code={error?.Code}, message={error?.Message}"); adListener.OnShowError(); @@ -114,7 +114,7 @@ public sealed class TapadnInteractionPlayer : ADPlayer, IDirichletInterstitialAu public void OnAdShow() { - TapadnSmartLoadOrchestrator.OnShowStart(AD_Type.Interaction, AdScene); + TapadnSmartLoadOrchestrator.OnShowStart(AD_Type.Interaction, AdScene, Key); NotifyShowStarted(); } @@ -136,12 +136,13 @@ public sealed class TapadnInteractionPlayer : ADPlayer, IDirichletInterstitialAu public override void OnPlayRequestStarted() { - TapadnSmartLoadOrchestrator.OnPlayRequestStarted(AD_Type.Interaction, AdScene, !UseAutoLoad() && IsReadly()); + TapadnSmartLoadOrchestrator.OnPlayRequestStarted(AD_Type.Interaction, AdScene, !UseAutoLoad() && IsReadly(), Key); } public override void EnterAdScenario(string scenario) { - TapadnSmartLoadOrchestrator.OnEnterAdScenario(AD_Type.Interaction, scenario, Key); + AdScene = string.IsNullOrWhiteSpace(scenario) ? "__default__" : scenario.Trim(); + TapadnSmartLoadOrchestrator.OnEnterAdScenario(AD_Type.Interaction, AdScene, Key); } private bool UseAutoLoad() @@ -151,7 +152,7 @@ public sealed class TapadnInteractionPlayer : ADPlayer, IDirichletInterstitialAu private void OnManualShown() { - TapadnSmartLoadOrchestrator.OnShowStart(AD_Type.Interaction, AdScene); + TapadnSmartLoadOrchestrator.OnShowStart(AD_Type.Interaction, AdScene, Key); NotifyShowStarted(); } diff --git a/Tapadn_Adapter/Runtime/Scripts/TapadnSmartLoadOrchestrator.cs b/Tapadn_Adapter/Runtime/Scripts/TapadnSmartLoadOrchestrator.cs index 1e27c6d..36fd46f 100644 --- a/Tapadn_Adapter/Runtime/Scripts/TapadnSmartLoadOrchestrator.cs +++ b/Tapadn_Adapter/Runtime/Scripts/TapadnSmartLoadOrchestrator.cs @@ -15,7 +15,7 @@ public static class TapadnSmartLoadOrchestrator private static TapadnSmartLoadConfig _runtimeConfig; private static Dictionary _states = new Dictionary(StringComparer.Ordinal); private static Dictionary _policies = new Dictionary(StringComparer.Ordinal); - private static Dictionary _cacheStates = new Dictionary(); + private static Dictionary _cacheStates = new Dictionary(StringComparer.Ordinal); private static bool _initialized; private static bool _enabled; @@ -116,7 +116,7 @@ public static class TapadnSmartLoadOrchestrator _enabled = options?.SmartPreloadEnabled ?? false; _initialized = true; _states = new Dictionary(StringComparer.Ordinal); - _cacheStates = new Dictionary(); + _cacheStates = new Dictionary(StringComparer.Ordinal); LoadStates(); EnsureDefaultPolicies(_runtimeConfig); } @@ -135,10 +135,10 @@ public static class TapadnSmartLoadOrchestrator record.ShowRequestCount = Math.Max(0, record.ShowRequestCount); SaveStates(); - TryPreload(adType, normalizedScenario); + TryPreload(adType, normalizedScenario, _slotId); } - public static void OnPlayRequestStarted(AD_Type adType, string scenario, bool cacheReadyAtRequest) + public static void OnPlayRequestStarted(AD_Type adType, string scenario, bool cacheReadyAtRequest, string slotId = null) { if (!_initialized || !_enabled) { @@ -152,49 +152,49 @@ public static class TapadnSmartLoadOrchestrator record.LastUpdatedUnix = GetNowUnixSeconds(); if (cacheReadyAtRequest) { - MarkImmediateHit(adType, normalizedScenario); + MarkImmediateHit(adType, normalizedScenario, slotId); } else { - MarkCacheExpiredIfStale(adType); + MarkCacheExpiredIfStale(adType, slotId); } SaveStates(); } - public static void OnLoadRequested(AD_Type adType, string scenario) + public static void OnLoadRequested(AD_Type adType, string scenario, string slotId = null) { if (!_initialized || !_enabled) { return; } - PrepareSmartLoadRequest(adType, scenario); + PrepareSmartLoadRequest(adType, scenario, slotId); } - public static void OnLoadStarted(AD_Type adType, string scenario) + public static void OnLoadStarted(AD_Type adType, string scenario, string slotId = null) { if (!_initialized || !_enabled) { return; } - BeginLoadRequest(adType, scenario); + BeginLoadRequest(adType, scenario, slotId); SaveStates(); } - public static void OnLoadResult(AD_Type adType, string scenario, bool success) + public static void OnLoadResult(AD_Type adType, string scenario, bool success, string slotId = null) { if (!_initialized || !_enabled) { return; } - CompleteLoadRequest(adType, scenario, success); + CompleteLoadRequest(adType, scenario, success, slotId); SaveStates(); } - public static void OnShowStart(AD_Type adType, string scenario) + public static void OnShowStart(AD_Type adType, string scenario, string slotId = null) { if (!_initialized || !_enabled) { @@ -204,11 +204,11 @@ public static class TapadnSmartLoadOrchestrator var record = GetOrCreateState(adType, NormalizeScenario(scenario)); record.ShowStartCount = Math.Max(0, record.ShowStartCount) + 1; record.LastUpdatedUnix = GetNowUnixSeconds(); - MarkCacheConsumed(adType, scenario); + MarkCacheConsumed(adType, scenario, slotId); SaveStates(); } - public static void OnShowError(AD_Type adType, string scenario) + public static void OnShowError(AD_Type adType, string scenario, string slotId = null) { if (!_initialized || !_enabled) { @@ -218,11 +218,11 @@ public static class TapadnSmartLoadOrchestrator var record = GetOrCreateState(adType, NormalizeScenario(scenario)); record.ShowFailureCount = Math.Max(0, record.ShowFailureCount) + 1; record.LastUpdatedUnix = GetNowUnixSeconds(); - MarkCacheShowFailed(adType, scenario); + MarkCacheShowFailed(adType, scenario, slotId); SaveStates(); } - private static void TryPreload(AD_Type adType, string scenario) + private static void TryPreload(AD_Type adType, string scenario, string slotId) { if (!_initialized || !_enabled) { @@ -257,11 +257,11 @@ public static class TapadnSmartLoadOrchestrator return; } - MarkCacheExpiredIfStale(adType); - OnLoadRequested(adType, scenario); + MarkCacheExpiredIfStale(adType, slotId); + OnLoadRequested(adType, scenario, slotId); ADManager.Instance.LoadAD(adType); - var smartLoadStarted = HasPendingSmartLoadForScene(adType, scenario); - ClearPreparedLoadIfNotStarted(adType); + var smartLoadStarted = HasPendingSmartLoadForScene(adType, scenario, slotId); + ClearPreparedLoadIfNotStarted(adType, slotId); if (!smartLoadStarted) { return; @@ -302,9 +302,9 @@ public static class TapadnSmartLoadOrchestrator return Mathf.Lerp(policy.BaseProbability, observedRate, trust); } - private static void PrepareSmartLoadRequest(AD_Type adType, string scenario) + private static void PrepareSmartLoadRequest(AD_Type adType, string scenario, string slotId) { - var state = GetOrCreateCacheState(adType); + var state = GetOrCreateCacheState(adType, slotId); if (state.PendingSmartLoad) { return; @@ -316,9 +316,9 @@ public static class TapadnSmartLoadOrchestrator state.PreparedRequestUnix = GetNowUnixSeconds(); } - private static void BeginLoadRequest(AD_Type adType, string scenario) + private static void BeginLoadRequest(AD_Type adType, string scenario, string slotId) { - var state = GetOrCreateCacheState(adType); + var state = GetOrCreateCacheState(adType, slotId); var now = GetNowUnixSeconds(); if (state.PreparedSmartLoad) { @@ -346,9 +346,9 @@ public static class TapadnSmartLoadOrchestrator state.PreparedRequestUnix = 0; } - private static void ClearPreparedLoadIfNotStarted(AD_Type adType) + private static void ClearPreparedLoadIfNotStarted(AD_Type adType, string slotId) { - var state = GetOrCreateCacheState(adType); + var state = GetOrCreateCacheState(adType, slotId); if (state.PendingSmartLoad) { return; @@ -360,16 +360,16 @@ public static class TapadnSmartLoadOrchestrator state.PreparedRequestUnix = 0; } - private static bool HasPendingSmartLoadForScene(AD_Type adType, string scenario) + private static bool HasPendingSmartLoadForScene(AD_Type adType, string scenario, string slotId) { - var state = GetOrCreateCacheState(adType); + var state = GetOrCreateCacheState(adType, slotId); return state.PendingSmartLoad && string.Equals(NormalizeScenario(state.PendingOriginScene), NormalizeScenario(scenario), StringComparison.Ordinal); } - private static void CompleteLoadRequest(AD_Type adType, string scenario, bool success) + private static void CompleteLoadRequest(AD_Type adType, string scenario, bool success, string slotId) { - var cacheState = GetOrCreateCacheState(adType); + var cacheState = GetOrCreateCacheState(adType, slotId); var normalizedScenario = NormalizeScenario(scenario); var originScene = cacheState.PendingSmartLoad ? NormalizeScenario(cacheState.PendingOriginScene) : normalizedScenario; var originRecord = GetOrCreateState(adType, originScene); @@ -408,23 +408,23 @@ public static class TapadnSmartLoadOrchestrator cacheState.PendingRequestUnix = 0; } - private static void MarkImmediateHit(AD_Type adType, string scenario) + private static void MarkImmediateHit(AD_Type adType, string scenario, string slotId) { var consumedScene = NormalizeScenario(scenario); var currentSceneRecord = GetOrCreateState(adType, consumedScene); currentSceneRecord.ImmediateHitCount = Math.Max(0, currentSceneRecord.ImmediateHitCount) + 1; currentSceneRecord.LastUpdatedUnix = GetNowUnixSeconds(); - var cacheState = GetOrCreateCacheState(adType); + var cacheState = GetOrCreateCacheState(adType, slotId); if (!cacheState.HasReadyCache) { currentSceneRecord.UnattributedCacheHitCount = Math.Max(0, currentSceneRecord.UnattributedCacheHitCount) + 1; } } - private static void MarkCacheConsumed(AD_Type adType, string scenario) + private static void MarkCacheConsumed(AD_Type adType, string scenario, string slotId) { - var cacheState = GetOrCreateCacheState(adType); + var cacheState = GetOrCreateCacheState(adType, slotId); if (!cacheState.HasReadyCache || cacheState.Consumed) { return; @@ -458,9 +458,9 @@ public static class TapadnSmartLoadOrchestrator ClearReadyCache(cacheState); } - private static void MarkCacheShowFailed(AD_Type adType, string scenario) + private static void MarkCacheShowFailed(AD_Type adType, string scenario, string slotId) { - var cacheState = GetOrCreateCacheState(adType); + var cacheState = GetOrCreateCacheState(adType, slotId); if (!cacheState.HasReadyCache) { return; @@ -479,9 +479,9 @@ public static class TapadnSmartLoadOrchestrator ClearReadyCache(cacheState); } - private static void MarkCacheExpiredIfStale(AD_Type adType) + private static void MarkCacheExpiredIfStale(AD_Type adType, string slotId) { - var cacheState = GetOrCreateCacheState(adType); + var cacheState = GetOrCreateCacheState(adType, slotId); if (!cacheState.HasReadyCache) { return; @@ -502,9 +502,9 @@ public static class TapadnSmartLoadOrchestrator ClearReadyCache(cacheState); } - private static TapadnSmartLoadCacheState GetOrCreateCacheState(AD_Type adType) + private static TapadnSmartLoadCacheState GetOrCreateCacheState(AD_Type adType, string slotId) { - var key = (int)adType; + var key = ComposeCacheKey(adType, slotId); if (_cacheStates.TryGetValue(key, out var state) && state != null) { return state; @@ -879,6 +879,16 @@ public static class TapadnSmartLoadOrchestrator return ((int)adType) + "|" + NormalizeScenario(scenario); } + private static string ComposeCacheKey(AD_Type adType, string slotId) + { + return ((int)adType) + "|" + NormalizeSlotId(slotId); + } + + private static string NormalizeSlotId(string slotId) + { + return string.IsNullOrWhiteSpace(slotId) ? "__default_slot__" : slotId.Trim(); + } + private static string NormalizeScenario(string scenario) { if (string.IsNullOrWhiteSpace(scenario)) diff --git a/Tapadn_Adapter/Runtime/Scripts/TapadnSplashPlayer.cs b/Tapadn_Adapter/Runtime/Scripts/TapadnSplashPlayer.cs index 55e03c8..1e00d13 100644 --- a/Tapadn_Adapter/Runtime/Scripts/TapadnSplashPlayer.cs +++ b/Tapadn_Adapter/Runtime/Scripts/TapadnSplashPlayer.cs @@ -56,12 +56,12 @@ public sealed class TapadnSplashPlayer : ADPlayer, IDirichletSplashAutoAdListene } curState = 1; - TapadnSmartLoadOrchestrator.OnLoadStarted(AD_Type.Splash, AdScene); + TapadnSmartLoadOrchestrator.OnLoadStarted(AD_Type.Splash, AdScene, Key); _adNative.LoadSplashAd( TapadnAdRequestFactory.BuildSplash(Key, TapadnAdController.CurrentOptions), ad => { - TapadnSmartLoadOrchestrator.OnLoadResult(AD_Type.Splash, AdScene, true); + TapadnSmartLoadOrchestrator.OnLoadResult(AD_Type.Splash, AdScene, true, Key); _loadedAd?.Destroy(); _loadedAd = ad; _loadedAd.Shown += OnManualShown; @@ -73,7 +73,7 @@ public sealed class TapadnSplashPlayer : ADPlayer, IDirichletSplashAutoAdListene }, error => { - TapadnSmartLoadOrchestrator.OnLoadResult(AD_Type.Splash, AdScene, false); + TapadnSmartLoadOrchestrator.OnLoadResult(AD_Type.Splash, AdScene, false, Key); curState = 0; Debug.LogError($"[TapADN] Splash load failed. code={error.Code}, message={error.Message}"); }); @@ -106,7 +106,7 @@ public sealed class TapadnSplashPlayer : ADPlayer, IDirichletSplashAutoAdListene } _showSettled = true; - TapadnSmartLoadOrchestrator.OnShowError(AD_Type.Splash, AdScene); + TapadnSmartLoadOrchestrator.OnShowError(AD_Type.Splash, AdScene, Key); curState = 0; Debug.LogError($"[TapADN] Splash show failed. code={error?.Code}, message={error?.Message}"); adListener.OnShowError(); @@ -114,7 +114,7 @@ public sealed class TapadnSplashPlayer : ADPlayer, IDirichletSplashAutoAdListene public void OnAdShow() { - TapadnSmartLoadOrchestrator.OnShowStart(AD_Type.Splash, AdScene); + TapadnSmartLoadOrchestrator.OnShowStart(AD_Type.Splash, AdScene, Key); NotifyShowStarted(); } @@ -136,12 +136,13 @@ public sealed class TapadnSplashPlayer : ADPlayer, IDirichletSplashAutoAdListene public override void OnPlayRequestStarted() { - TapadnSmartLoadOrchestrator.OnPlayRequestStarted(AD_Type.Splash, AdScene, !UseAutoLoad() && IsReadly()); + TapadnSmartLoadOrchestrator.OnPlayRequestStarted(AD_Type.Splash, AdScene, !UseAutoLoad() && IsReadly(), Key); } public override void EnterAdScenario(string scenario) { - TapadnSmartLoadOrchestrator.OnEnterAdScenario(AD_Type.Splash, scenario, Key); + AdScene = string.IsNullOrWhiteSpace(scenario) ? "__default__" : scenario.Trim(); + TapadnSmartLoadOrchestrator.OnEnterAdScenario(AD_Type.Splash, AdScene, Key); } private bool UseAutoLoad() @@ -151,7 +152,7 @@ public sealed class TapadnSplashPlayer : ADPlayer, IDirichletSplashAutoAdListene private void OnManualShown() { - TapadnSmartLoadOrchestrator.OnShowStart(AD_Type.Splash, AdScene); + TapadnSmartLoadOrchestrator.OnShowStart(AD_Type.Splash, AdScene, Key); NotifyShowStarted(); } diff --git a/package.json b/package.json index cbcf410..e9a4553 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "com.commercialization.tapadn", "displayName": "Commercialization.tapadn", "description": "TapADN / Dirichlet mediation implementation for CC-Framework.Commercialization.", - "version": "1.0.3", + "version": "1.0.4", "unity": "2022.3", "license": "MIT", "repository": {