猛攻兄弟为广告系统做了哪些努力
04/12194 浏览开发心得 包含 AI 合成内容
在游戏中接入激励视频广告
看似只是让嗒拉拉调一个 SDK 接口的事
但真正投入生产后你会发现
难的是之后如雪片飞来的差评
本文分享我在广告系统上踩过的坑和最终的工程方案。
一、问题背景:广告 SDK 没你想的那么可靠
激励视频广告的标准流程很简单:
用户点击 → SDK 弹出广告 → 用户看完 → SDK 回调 → 发放奖励
但在真实小游戏环境中,这个流程经常断裂:
- SDK 回调丢失:广告播放完毕,但 SDK 的成功回调永远不来,游戏卡在"广告播放中"的黑屏状态
- 进程被杀:用户看广告时切到后台,系统回收内存杀掉进程,奖励没发出去
- 焦点丢失:跳转外部浏览器或应用商店后返回,游戏状态错乱
- 无法确认结果:用户回来了,但不确定广告是否真的播完了
这些问题单独看都不大,但组合起来足以让玩家体验崩塌
黑屏、卡死、丢奖励,每一个都是差评来源。
每个差屏可能导致平台曝光下降,下降就代表收入降低,这是致死的问题,不能不解决。
而且愿意留负评的人其实是远大于留好评的,毕竟作的好是应该,做不好是欠骂,能避就避!!
二、解法 1:广告会话追踪——消灭黑屏
核心思路
不再信任 SDK 回调作为唯一判据,而是引入一个独立的**广告会话(AdSession)**状态机,自己掌控广告的生命周期。
三层防线
第一层:SDK 正常回调
最理想的情况。SDK 回调到达时,标记 resolved = true,正常发放或拒绝奖励。这一层处理 95% 以上的场景。
第二层:焦点恢复 + 宽限期
当 SDK 回调丢失时,游戏会监听操作系统级别的焦点恢复事件(InputFocus)。一旦检测到用户从广告应用返回了游戏:
- 记录恢复时间戳
- 给 SDK 一个短暂的宽限期(零点几秒)等待迟到的回调
- 宽限期结束后 SDK 仍然没有回调 → 强制结束会话,视为成功
为什么视为成功?因为用户确实从广告页面返回了,大概率是看完了。即使偶尔有误判,对玩家体验的损害也远小于黑屏卡死。
第三层:绝对超时兜底
如果连焦点恢复事件都没有触发(极端情况),设定一个绝对超时上限。超时后强制结束会话,此时由于无法确认用户是否看完,发放奖励,且至少保证游戏不会卡死。
效果
三层防线层层递进,确保无论 SDK 行为出现异常时,游戏都不会卡在"广告播放中"的状态。实际上线后,黑屏投诉有效降低。
但还没清零! 这事只能继续努力分析病因,想办法解决
三、解法 2:崩溃恢复——进程被杀也不丢奖励
问题本质
广告播放时,游戏进程随时可能被系统杀掉(内存不足、用户误操作等)。此时:
- SDK 回调不会触发
- 游戏内存中的所有状态丢失
- 玩家重新打开游戏,发现奖励没了
对于一个有复杂养成系统的割草 Roguelike 游戏来说,这不只是丢一点金币的问题——可能是整局的复活机会、宝箱奖励、结算倍率全部一次蒸发,绝对的负评产生器。
核心思路:先写后播
在广告播放之前,把"如果看完了应该给什么奖励"写入云端。

恢复缓存设计
缓存数据包含完整的恢复所需信息:

其中战斗复活的恢复较为取巧:正常流程是在战斗中原地复活继续打,但进程被杀后战斗状态无法恢复(怪物位置、子弹轨迹等全丢了,且怪物数据量较为庞大 包含数量、血量等状态)。
解决方案是跳过当前波次,直接进入下一波的商店阶段——玩家不会觉得亏了,因为获得了一次免费过关的机会。特殊情况是 BOSS 轮:不推进波数,留在当前波让玩家重新挑战 BOSS。
防刷机制
恢复系统天然面临被滥用的风险(故意杀进程触发恢复)。对策:
- 先清后发:转盘类奖励在恢复函数的最开头就清除缓存,即使转盘动画播放期间再次杀进程也不会重复触发
- 时效限制:缓存超过一定时间自动失效,过期直接丢弃
- claimed 标记:云端数据用 claimed = true 标记已领取,而非直接删除——因为在 Lua 中 table[key] = nil 会删除 key,同步到云端时这个 key 就不存在了,无法覆盖旧数据。这是实际踩过的坑
- 本次启动去重:用一个标志位记录是否已触发过恢复,防止同一次启动内重复执行
Flush 重试
还有一个工程细节:云端写入是异步的,如果恰好赶上上一次写入正在进行中(内部有个 flushing_ 锁),当前写入会被跳过。解决方案是在每帧更新中检查是否有待重试的 flush,持续重试直到缓存数据确实写入云端,然后才真正开始播放广告。
四、广告限额——看太多反而亏钱
一个反直觉的事实
你可能以为广告看得越多收益越高——事实恰恰相反。广告平台的竞价算法会根据用户的观看频率动态调整出价:同一个用户短时间内看太多次广告,平台判定该用户的广告价值递减,单次 eCPM 会持续走低。极端情况下,一个重度用户每天看 50 次广告带来的总收入,可能还不如另一个用户每天看 15 次。

简单说:广告不是越多越好,而是存在一个边际收益拐点。
因此我们给每个用户设定了每日真实广告上限。超过这个次数后,不再调用 SDK,而是自动跳过广告直接发放奖励:

4/9日疑似因为缺少新用户,全都是老用户在看导致收入跌落谷底

4/9日收益暴跌
具体每个用户每天能看多少次,没人能说清楚,但是你拉到底就会知道我的设定是多少。
终生限额
除了每日限额,还可以设置一个终生累计上限。一旦某个用户的历史总观看次数超过阈值,后续全部进入免费模式。曾看过有小游戏设定并告知玩家看100次就终生免广告 + 解锁特殊能力作为目标驱动的体验。
每日计数的服务端权威
计数不能只存客户端——太容易被篡改。我们的做法是:
- 服务端维护权威计数:每次广告成功/跳过都通过 RemoteEvent 上报
- 登录时同步:玩家每次登录从服务端拉取今日已看次数
- 跨天重置:检测到 UTC+8 日期变更时自动清零
这样即使客户端被修改,也无法突破限额获得额外的真实广告调用。
五、广告测试——不用真看广告也能测
痛点
测试广告相关功能时,几个现实问题让人抓狂:
- 必须先打一局游戏才能触发广告入口(结算翻倍要先打完、复活要先阵亡、宝箱要先通关……)
- 测试人员不可能每次都真的看完 30 秒广告
- 测试环境下广告 SDK 经常没有填充(no fill),根本播不出来
- 要验证的其实是广告之后的奖励逻辑(转盘倍率对不对、金币发没发、经验加没加),广告本身不是重点
归根结底:测试的核心是奖励机制,广告只是触发入口。但现实中,光是到达广告入口就要花大量时间。
广告跳过开关
第一个工具:一个全局的广告跳过开关。打开后,所有广告入口不再调用 SDK,而是直接执行奖励回调。
开关的效果:

一键看广告
第二个工具 : 在 GM 面板中提供一个一键触发广告的按钮,直接模拟各个场景的广告调用,完全跳过"先玩游戏才能触发"的前置流程。

打开 GM 面板 → 点一个按钮 → 验证奖励
一轮测试从几分钟缩短到几秒钟,效率提升一个数量级。
配合限额机制
测试模式和第四节的限额机制天然配合:
跳过开关开启时:广告不调用 SDK,计入"免费跳过"统计,不影响真实广告数据
跳过开关关闭时:正常走限额逻辑,测试人员也可以验证限额本身是否正确
两套机制互不干扰,测试环境和线上环境用同一套代码。
六、广告监控仪表盘——数据驱动决策
为什么需要监控
广告系统上线后,你需要回答这些问题:
- 玩家每天看了多少广告?
- 有多少次是主动跳过的?(广告质量差?还是奖励不够吸引?)
- 闪退率是多少?(SDK 稳定性如何?)
- 不同日期的表现有波动吗?
- 新用户和老用户的广告行为有差异吗?
不监控就是盲人摸象。
七维度指标体系
我定义了七个关键指标,覆盖广告的完整生命周期:

为什么成功率的公式是 (成功 - 闪退) / (点击-主动跳过)?
因为闪退恢复机制会把闪退也计入成功(毕竟发放了奖励),但从衡量 SDK 可靠性的角度看,闪退代表 SDK 行为异常,应该扣除才能反映真实的广告完成率。
存储采用最近 7 日周循环覆盖 + 生涯总榜,共 8 个维度。周循环让你能发现趋势(比如"周末广告表现比工作日好"),生涯总榜给你全局视角。
想作永久存储也不是不行,注意存储资料量的限制即可。
GM 监控面板
数据有了,还需要方便查看的界面。我们做了一个内置的 GM 面板,核心功能:

8 个标签页:周一到周日 + 生涯,一键切换,每个标签页显示日期
- 汇总行:一行看全貌——玩家总数、总点击、总成功、总闪退、成功率、免费跳过、主动跳过、超限拒绝
- 玩家排行榜:按玩家维度展开,每行显示 UID、首登日期和各项指标
- 新用户金色标记:当天新登录的玩家 UID 显示为金色,快速识别新用户的广告行为是否正常
- 点击 UID 复制:点击任意 UID 自动复制,一键跳转到广告调整工具
甚至 有大佬还能根据平台给的预估收益,去计算自己的预期收益,在面板上显示出来
七、广告调整工具——精准干预单个玩家
使用场景
监控面板解决的是"看全局"的问题,但有时候需要针对特定玩家做操作:
- 玩家投诉"看完广告没拿到奖励",需要帮她恢复可看次数,或是让他进入跳过环节
- 测试人员需要对特定账号调整广告参数来复现问题
工作流
监控面板和调整工具之间设计了一键联动:
- 在监控面板中发现异常玩家,点击 UID 复制
- 点击左上角"广告调整"按钮,UID 自动填入
- 查看该玩家的详细广告数据
- 必要时调整该玩家的广告参数


从发现问题到定位到调整,整个流程不需要离开游戏,也不需要登录后台系统,更不用手动输入(主要是我懒)。一条龙在游戏内完成。
八、总结
回顾整套方案
它不是某个单点优化,而是一个覆盖播放→恢复→限额→测试→监控→调整六个环节的完整体系
几条经验教训:
不要信任 SDK 回调——它可能丢、可能迟、可能重复。自己维护状态机,用焦点事件+超时做兜底。
先写后播——任何可能中断的操作,先把恢复数据持久化,再执行操作。数据库事务思维。
恢复策略因地制宜——有些场景可以精确恢复(弹转盘),有些只能近似恢复(跳过战斗进商店),关键是不让玩家觉得亏了。
广告不是越多越好——平台算法会惩罚过度曝光,设定合理限额后用免费奖励兜底,总 ROI 反而更高。
测试的核心是奖励机制——做一键触发按钮,跳过"先玩游戏才能看广告"的前置流程。
数据要分层——真实广告和免费跳过分开统计,才能看到 SDK 的真实表现。
nil 不能覆盖云端——Lua 的 table[k]=nil 等于删除 key,同步时 key 就不存在了。用 {claimed=true} 代替。
监控和调整要联动——看到问题后能一键定位到具体玩家并干预,闭环才有意义。
希望这些经验对正在做广告系统的开发者有帮助。
同时感谢 交流群大佬 宜糖予我心
她分享了关键参考数据 每日20次限额,还有对应的预期营收算法
下面是她的好游戏



