广告为什么必须晚于用户同意

人和 AI 一起做游戏 · 第 15 篇

《人和 AI 一起做游戏》第 15 篇:广告为什么必须晚于用户同意,Kibble Street TD 历史开发画面与流程图。

本篇依据截至 2026 年 8 月 3 日的开发记录,回顾 2026 年 6—7 月及 8 月初的开发过程。正文中的“当前”、数值、画面、候选资源与验证结论均指当时快照,不代表现售版本的状态。

上一篇:内购成功为什么不等于发奖成功

广告接入最容易产生的误解,是认为只有广告真正覆盖游戏画面时,隐私问题才开始。实际上,广告服务通常会在应用启动时初始化,随后联网、读取配置并提前加载内容。等玩家看到广告时,前面的请求可能早已发生。

《Kibble Street TD》最初需要解决的因此不是“广告放在哪里”,而是“广告服务什么时候才有资格启动”。如果先初始化,再补一个同意弹窗,界面顺序看似正确,网络请求的顺序却已经反了。

广告在展示之前就已经开始工作

当前启动链路会先更新 Google UMP 保存的同意信息。如果所在地区和当前状态需要表单,系统会加载并展示;只有 UMP 最终返回允许请求广告,游戏才会启动 Google Mobile Ads,随后进入预加载。

广告初始化之前的同意闸门
广告初始化之前的同意闸门

这里的闸门不是“弹窗有没有出现”,而是 canRequestAds 是否成立。已经保存的有效状态可能让广告服务直接启动,同时后台继续刷新同意信息;新用户或状态变化时,则可能先看到表单。没有表单不等于跳过合规,有表单也不等于一定允许请求广告。

如果最终仍不允许请求,当前正常路径会返回明确失败,不启动广告服务。游戏启动本身不会被广告阻断:广告初始化在旁路执行,失败会记录原因,玩家仍可继续进入首页和战斗。

这条边界很重要。广告是可选能力,隐私决定不能因为广告失败而被绕过;反过来,广告不可用也不应该让单机玩法无法启动。

UMP 和 ATT 不是同一个问题

UMP 负责的是地区、同意状态与广告隐私选项;ATT 处理的是跨应用追踪授权与 IDFA。两者都与广告有关,但不能用一个弹窗代替另一个,也不能因为接入了 UMP,就默认应用已经获得追踪授权。

UMP 与 ATT 的职责边界
UMP 与 ATT 的职责边界

《Kibble Street TD》当前版本不请求 ATT,也不读取 IDFA。工程内的隐私清单将追踪声明为关闭,同时列出广告、分析和应用功能实际涉及的数据用途。这只是当前实现选择,不是“一次配置永久合规”:广告依赖、数据用途或投放方式变化后,清单与后台声明都要重新核对。

同意也不只等于“接受个性化广告”。在某些状态下,用户拒绝个性化后,平台仍可能允许请求受限或非个性化广告。游戏不自行猜测结果,只读取 UMP 给出的最终许可状态。

隐私设置入口必须跟着地区状态变化

同意不是只能在首次启动时决定一次。部分地区要求应用长期提供广告隐私选项,让用户之后能够重新查看或调整选择。

Ad Privacy 入口的三种状态
Ad Privacy 入口的三种状态

当前设置页每次构建内容时都会查询要求状态。返回“必须提供”时,页面增加与 Privacy、Terms 同级的 Ad Privacy 入口,并打开 UMP 的隐私选项表单;返回“不需要”时不显示这行。查询失败或状态未知时,页面不会凭空展示一个无法工作的入口,而是记录错误并保留基础法律链接。

这意味着设置页不是写死的菜单。相同版本在不同地区、不同同意状态下,公开的入口可能不同。开发时如果只在自己的设备上看过一次,很容易误以为所有用户都获得了相同页面。

激励广告必须把“看见”和“获得奖励”分开

项目当前有商店奖励和战斗双倍奖励两类激励广告。玩家点击只是发起请求,广告开始展示也不是发奖依据。只有原生广告服务收到平台的“已经获得奖励”回调,并最终返回 rewarded 状态,业务层才执行增加资源或翻倍奖励。

激励广告从请求到发奖
激励广告从请求到发奖

如果玩家提前关闭、广告未就绪、已有另一条广告正在展示,或者加载与展示失败,链路都返回不发奖。广告结果与业务发奖结果还会分别记录:即使平台确认可以奖励,游戏保存资源时仍可能失败,这不能被包装成一次完整成功。

这个顺序与内购相似,都是先获得外部事实,再修改游戏状态;但广告没有一笔可以在下次启动继续履行的未完成交易。因此,激励广告的发奖失败仍需要真机验证和单独观察,不能直接照搬内购恢复方案。

插屏广告可以缺席,返回首页不能失败

战斗结算返回首页的插屏属于另一种广告。它不发奖励,也不是玩家主动交换资源,因此使用远程开关控制,客户端默认关闭。

插屏广告的软失败路径
插屏广告的软失败路径

开关关闭时,游戏不加载、不展示并清除已有缓存,点击 HOME 直接返回。开关开启后,只有广告已经就绪才可能展示;未填充、加载失败、展示失败或没有准备好,都只记录结果,然后继续返回首页,不弹出错误提示。

远程开关解决的是运营时机,不是隐私许可。正确顺序仍然是:先通过同意闸门,广告服务能够启动以后,远程配置才有资格决定某个点位是否加载。关闭点位不能替代 UMP,开启点位也不能越过 UMP。

测试环境要与真实投放分开

编辑器使用可控的模拟广告,模拟器强制使用平台测试广告位,只有 iOS 真机才读取正式广告配置。这样日常开发不会制造无效流量,也不会把模拟器成功误写成正式广告可用。

当前专项检查已经覆盖广告配置、初始化终态、预加载去重、激励广告关闭不发奖、发奖回调失败、插屏返回状态和远程开关默认关闭;隐私清单与基础配置文件也能通过格式检查。

但合规链路还有一个必须修正的缺口:正常构建已经声明 UMP 依赖,正常路径也会在 canRequestAds=false 时阻止广告启动;如果构建意外缺少 UMP,现有兼容分支却会继续启动广告。这与“缺少同意能力就阻断”的发布规则相反,提交前应改为明确失败。

广告链路的完成项与待办项
广告链路的完成项与待办项

同时,当前还没有真实设备上的同意表单、Ad Privacy 入口、激励广告奖励、插屏开关与关闭路径证据,也没有把广告后台配置写成已经验收。静态合同通过、模拟流程正确和真实地区合规,是三种不同结论。

人和 AI 分别负责什么

AI 适合沿启动顺序扫描同意更新、服务初始化、预加载、展示和奖励回调,检查某个失败分支会不会继续请求广告。它也能把三类点位的状态与事件逐项对照,发现“广告关闭却发奖”或“插屏失败阻断页面跳转”这样的合同错误。

人负责决定产品边界:哪些广告是玩家主动选择,哪些只是可缺席的商业化点位;当前版本是否请求追踪;什么真实设备和地区证据足以进入发布结论。隐私与投放后台也需要人在实际账号下完成,不能由本地模拟代替。

如果你想开始

先把“广告初始化”从应用启动代码里单独圈出来,确认它前面是否存在平台许可闸门。再分别画出激励广告和插屏广告:谁发起、什么结果允许发奖、失败后页面是否还能继续、用户从哪里重新打开隐私选项。

最后至少验证四个状态:首次需要表单、已有有效状态、不允许请求广告、需要再次显示隐私入口。四条路径没有混在一起,广告接入才算真正开始。