# TapADN 自动加载策略分析报告

## 结论先行

当前 `Commercialization.tapadn` 的 auto 接入调用了 TapADN / Dirichlet 官方 Unity SDK 提供的 Android auto-ad API，接口使用方向是正确的：激励视频走 `ShowRewardVideoAutoAd`，插屏走 `ShowInterstitialAutoAd`，开屏走 `ShowSplashAutoAd`，激励视频额外按 SDK 注释使用 `PreLoad(request, 3)`。

但不能把 TapADN 的 auto 与 TopOn 的全自动加载视为同一种能力。TopOn 的 auto 是一套更完整的广告位请求维护方案，包含广告位注册、真实 ready 查询、场景进入统计、缓存状态统计和自动续载；TapADN 当前 Unity wrapper 暴露的是“加载 + 展示合并”的 auto show API，没有看到类似 `entryAutoAdScenarioWithPlacementID` 的场景入口，也没有看到 auto ready 查询 API。

因此，生产默认策略建议改为“默认全部手动”，并保留每类广告的开关用于分场景 AB。原因是：

* 当前 `AsyncAdPlayer` 已经承载了 ready/load/show 的生命周期统一，手动模式更能把回调和失败收口稳定在框架层。
* 上层仍会调用 `ADManager.EnterAdScenario(...)`，这更适合我们把策略判断放到“场景上”，而不是让 SDK 的 auto 接口替代场景决策。

## 问题定义

这次校对的核心不是“auto API 能不能调用”，而是要判断它是否适合作为 IAA 游戏商业化模块的默认策略：

* IAA 游戏的收益优化通常不是按广告类型粗放处理，而是按广告场景处理，例如复活、翻倍奖励、关卡结束、失败结算、返回大厅、冷启动开屏。
* 顶部聚合平台的自动加载能力通常还承担缓存命中、场景到达率、展示率和频控策略的统计基础。
* 若 SDK auto 只能在 show 时兜底加载，业务侧把它当作“已准备好”会引入延迟、失败回调、误展示时机和广告场景数据缺失。

## 当前 TapADN 实现状态

当前模块默认配置位于 `Assets/Tapadn_Adapter/Runtime/Scripts/TapadnControllerOptions.cs`：

 * `RewardedAutoLoad = false`
 * `InterstitialAutoLoad = false`
 * `SplashAutoLoad = false`
* `RewardedPrewarmOnInit`、`InterstitialPrewarmOnInit`、`SplashPrewarmOnInit` 默认为 `false`

三个播放器的 auto 分支行为如下：

* 激励视频：`LoadAD()` 中调用 `PreLoad(request, 3)`；`ShowAD()` 中调用 `ShowRewardVideoAutoAd(...)`。
* 插屏：`LoadAD()` 只把本地状态置为可播放；`ShowAD()` 调用 `ShowInterstitialAutoAd(...)`。
* 开屏：`LoadAD()` 只把本地状态置为可播放；`ShowAD()` 调用 `ShowSplashAutoAd(...)`。

这个实现和 TapADN 当前 SDK wrapper 的能力匹配，但有一个重要语义差异：auto 模式下 `IsReadly()` 实际上只能证明广告位 id 合法，不能证明广告已经填充并可立即展示。激励视频由于有 `PreLoad(type=3)`，缓存命中概率会更好；插屏和开屏在当前 wrapper 中没有对应 preload 能力，show-time 加载的风险更明显。

## TopOn 全自动加载机制对照

`Commercialization.topon` 的设计更接近平台完整自动加载模型：

* 初始化或使用前通过 `addAutoLoadAdPlacementID` 注册广告位。
* 展示前通过 `autoLoadRewardedVideoReadyForPlacementID` / `autoLoadInterstitialAdReadyForPlacementID` 查询真实 ready 状态。
* 进入业务广告场景时调用 `entryAutoAdScenarioWithPlacementID(placementId, scenario)`。
* 手动模式也有 `entryScenarioWithPlacementID(placementId, scenario)`，保证场景到达统计不只绑定 auto 模式。

TopOn 官方文档也明确把全自动加载定义为“一站式请求维护方案”，会根据用户使用状态和广告消耗进度判断下一条广告的预加载和缓存时机，并建议进入可展示广告的业务场景后调用 `entryAdScenario(placementId, scenarioId)` 统计缓存状态。也就是说，用户之前的判断是对的：TopOn 的 auto 不只是少写一次 load，它确实和“广告场景切分 + 缓存状态统计 + 展示决策”绑定在一起。

## TapADN 官方 auto 机制对照

TapADN / Dirichlet Unity 文档对 auto 的描述主要是“加载和展示合并为一次调用，内部自动管理广告缓存；若有可用缓存则立即展示，否则自动加载后展示”。官方文档中：

* 激励视频 `ShowRewardVideoAutoAd` 标注为推荐、Android only。
* 插屏 `ShowInterstitialAutoAd` 标注为推荐、Android only。
* 开屏 `ShowSplashAutoAd` 标注为推荐、Android only。
* 最佳实践仍然写到“在关键节点提前加载广告，展示后及时销毁并重新请求”，以及“结合业务实现频次限制”。

本地 SDK 注释进一步约束了能力边界：

* `PreLoad` 当前只有 type=3，即激励视频，会被 native SDK 处理。
* iOS 没有官方 native auto 缓存语义；当前模块会对激励、插屏、开屏 auto API 做 load-then-show 兼容 fallback，`PreLoad` 仍为 noop。
* Android bridge 中为 auto ad 保留了 singleton `DirichletAdNative`，用于保持 native 侧自动广告缓存。

当前接入严格遵循了这些 TapADN API，但没有也不能补出 TopOn 那种场景入口，因为当前 SDK wrapper 没有暴露同类接口。`ADManager.EnterAdScenario(...)` 对 TapADN 玩家侧目前没有平台上报效果，只能作为项目自身策略或日志的入口继续扩展。

## IAA 游戏策略判断

从全球和中国 IAA 游戏的通用经验看，默认策略应该围绕“广告位是否必须确定可展示”和“展示时机是否允许等待”来定：

* 激励视频是用户主动选择，通常用于复活、翻倍、补体力、开宝箱。这里最怕的是用户点击后广告不可用或等待过久，所以按钮是否可点最好来自真实 ready 状态。TapADN auto 可降低接入复杂度，但若 reward 场景价值高，手动 preload + ready gating 更稳。
* 插屏是非自愿打断，适合关卡间、结算后、自然暂停点。这里最怕误打断、过频和 show-time 卡顿，因此应该由业务频控、冷却和场景判断主导。没有真实 ready 查询时，默认手动更可控。
* 开屏在中国安卓渠道更常见，但冷启动时长、首屏流失和合规压力都更敏感。若 auto show 触发后再加载，失败或超时都直接影响进主场景体验；生产上更适合手动加载、严格超时和无广告快速进入。
* 顶级 IAA 调优更关注 placement / scenario 维度，而不是“这个类型是不是 auto”。同一个激励视频，复活、翻倍金币、免费抽奖的 eCPM、转化率和留存影响都可能不同，需要可分桶、可频控、可 A/B。

所以，模块层应该把 auto 当作“TapADN Android 的一种展示通道”；iOS 兼容 fallback 只能保证回调链路完整，不应被当成同等的 native 缓存策略。

## 推荐默认配置

建议在生产项目里按如下方式显式配置：

```text
tapadn.rewarded_auto_load=false
tapadn.rewarded_prewarm_on_init=false （建议改用入口驱动的手动 preload）

tapadn.interstitial_auto_load=false
tapadn.interstitial_prewarm_on_init=false

tapadn.splash_auto_load=false
tapadn.splash_prewarm_on_init=false
```

如果你想走“上层智能策略”也可以让默认逻辑保持上面的配置，再在高概率收益场景按策略临时开 auto 进行实验。必须完成以下验证：

* auto 模式下点击激励按钮到 `OnAdShow` 的延迟分布。
* auto 模式下 show fail、load fail、close、reward verify 是否都被 `ADManager` 收口。
* 插屏在自然断点触发时是否会出现明显等待、黑屏或重复请求。
* 开屏失败或无填充时是否能按产品要求进入主场景。
* 每个业务广告场景是否有自己的埋点、频控和远程配置。

## 内部智能策略建议（结合场景声明）

上层仍然在 `ADManager.EnterAdScenario(adType, scenario)` 里会声明场景，这个入口可以成为 TapADN 的控制平面。建议用一个本地策略层（或接入现有 remote config）来替代“固定 auto 默认”。核心规则建议:

* 入场闸门：新手 / 首次会话内降低开屏和插屏频率，设置较长冷却。
* 价值分层：`resume_continue`、`revive`、`double_reward`、`level_complete`、`session_end` 使用不同触发阈值。
* 预算分发：按场景给定每小时/每日展示配额，按最近 N 次 fill 成功率和关闭率动态降权。
* 失败避障：对连续 fail 场景计入惩罚分，自动降级到手动模式或延后下一次尝试。
* 回落路径：场景声明后可先触发预加载（手动），再在 `AsyncPlayAD` 时做 ready 判断，避免 show 时阻塞。

### 实战落地推荐（先做这 4 件）

为了先上线再迭代，这版实验建议按下面节奏推进（先保守后扩展）：

1. 先做“是否预加载”二分类决策
   - 输入：场景进入次数 / 播放请求次数 / 最近一次更新距今时长
   - 输出：`preload_score` 与 `cooldown`
   - 初始阈值：`score >= threshold && cooldown 过期`

2. 再加“场景独立配置表”
   - 默认配置放在 `TapadnSmartLoadPolicy_Default.json`（本地资源表）
   - 支持服务端覆盖配置（`tapadn.smart_preload_remote_json`）
   - 场景命中优先、无命中回退到该位 default

3. 建立在线反馈回路（每 1~3 天可更新）
   - `enter_count` / `play_request_count` + `fill 成功率`
   - `show_success - close 率` 作为质量约束（用于上调/下调阈值）

4. 降噪与退化
   - 连续低效场景自动降 `threshold`、拉长 `cooldown`
   - 连续高效场景适当提高预加载优先级

这样比“固定 always auto”更安全：能先守住体验（手动 show 生命周期），再逐步把预加载放到高价值场景。

这样我们保持框架语义：`AsyncAdPlayer` 负责生命周期和回调收口，场景策略只负责“该不该、何时、给谁”。

## 当前实现评价

当前 TapADN auto 接入本身是合规且完整的 API 级接入，但默认策略偏激进。它适合样例工程和快速调试；对于 Android/iOS 同步上线的正式 IAA 游戏商业化，建议把默认认知改成：

* TapADN auto 负责“SDK 内部 load + show + 缓存复用”。
* 项目商业化策略仍然负责“场景进入、ready gating、频控、冷却、奖励发放、A/B 分桶和兜底路径”。
* TopOn 的 auto 与 TapADN 的 auto 不等价，不能直接迁移 TopOn 的策略假设。

如果后续希望补齐 TopOn 风格的体验，可以在 `CC-Framework.Commercialization` 或 TapADN adapter 上层加一个本地策略层：

* `scenario -> ad type -> slot id/config` 映射。
* 每场景冷却、每日次数、会话次数、首局保护、新用户保护。
* 自有 `EnterAdScenario` 埋点，不依赖 SDK 是否支持场景 API。
* 对 TapADN auto 模式记录 show 请求、show 成功、show 失败、奖励验证和关闭，用数据判断是否继续 auto。

## 参考资料

* [Dirichlet 聚合 SDK Unity 接入文档](https://ssp.dirichlet.cn/docs/dirichlet-mediation-sdk/dirichlet-mediation-sdk-guide-unity/)
* [TopOn Fully automatic loading](https://help.toponad.net/docs/Fully-automatic-loading)
* [TopOn 全自动加载激励视频](https://help.toponad.net/cn/docs/Xactf8)
* [Google AdMob interstitial implementation guidance](https://support.google.com/admob/answer/6066980?hl=en)
* [Google AdMob recommended interstitial implementations](https://support.google.com/admob/answer/6201350?hl=en)
* [Google AdMob frequency capping](https://support.google.com/admob/answer/6244508?hl=en)
* [Unity LevelPlay placement best practices](https://docs.unity.com/grow/levelplay/platform/best-practices/placement)

## 仿真验收输出（新增）

为便于快速比较 `threshold / cooldown` 对用户体验与 waste 的影响，本模块附带一套敏感度脚本产物，默认次留目标为 35%：

- 报告：`Tools/SmartLoadSensitivity/output/TapADN_智能预加载_敏感度验收报告.md`
- 明细 CSV：`Tools/SmartLoadSensitivity/output/smartload_sensitivity_summary.csv`
- 排名 CSV：`Tools/SmartLoadSensitivity/output/smartload_retention_rank.csv`
- 图表：`Tools/SmartLoadSensitivity/output/*.png`

常用可视化入口（打开仓库根目录）：

- [热力图（35%次留）](Tools/SmartLoadSensitivity/output/heatmap_immediate_r_0.35.png)
- [平均时延（35%次留）](Tools/SmartLoadSensitivity/output/heatmap_wait_ms_r_0.35.png)
- [Waste 热力图（35%次留）](Tools/SmartLoadSensitivity/output/heatmap_waste_ratio_r_0.35.png)
- [留存变化线（即时性）](Tools/SmartLoadSensitivity/output/line_immediate_vs_retention.png)
- [留存变化线（时延）](Tools/SmartLoadSensitivity/output/line_wait_vs_retention.png)

脚本运行命令：

```bash
python Tools/SmartLoadSensitivity/smartload_sensitivity_simulation.py --users 5000 --out-dir Tools/SmartLoadSensitivity/output
```
