1. 为什么插屏广告是微信小游戏不可或缺的一环做微信小游戏的人应该都有同感流量主后台里最容易被人忽略的广告位往往就是插屏广告。很多人一上来就盯激励视频觉得插屏单价低、打扰用户实际上这是对插屏广告的误解。我最初做小游戏变现时也是这样直到把插屏接入进去、经过几轮数据对比后才发现它对整体收益的贡献远超预期。插屏广告本质上是一种“半屏强提醒”的广告形态通常出现在应用内的自然切换节点比如关卡结束、页面返回、结算弹出前后。它在微信小游戏里的实现方式和App端类似但多了一层小游戏运行环境带来的限制和机会。它不像横幅广告那样常驻视野也不像激励视频那样需要用户主动点击观看而是系统在合适的时机主动展示用户可以选择关闭也可以选择点击跳转。我之前在某团队做休闲游戏项目时刚开始只接入激励视频后来在版本更新时顺手加了插屏广告。上线一周后流量主后台的数据让整个项目组都改了态度插屏广告的填充率和eCPM虽然不如激励视频稳定但胜在展示频次高、介入自然不用用户额外操作只要展示时机合理用户不会反感反而能成为激励视频之外的“第二收入曲线”。尤其在休闲类、超休闲类游戏里插屏广告展示产生的收入甚至可以接近激励视频的40%甚至更高。那篇文章要解决的就是“如何在团结引擎开发的微信小游戏里正确、可控地接入插屏广告”。这里的关键词不是“能跑通”而是“可控”什么时候加载、什么时候展示、展示失败怎么兜底、频控怎么设置、如何避免影响体验。这些都是把广告接入从“能用”做到“好用”的分水岭。对于已经做过原生微信小游戏、熟悉wx.createInterstitialAd接口的人来说这篇文章能帮你快速把逻辑迁移到团结引擎环境对于刚接触Unity转小游戏的新手这篇文章也能让你少走至少一周的弯路。2. 接入前的环境准备2.1 团结引擎构建微信小游戏的基础条件先明确一点团结引擎对微信小游戏的支持本质上是在Unity原有工作流上增加了一层导出和适配。小游戏运行的是 JavaScript 逻辑Unity 游戏会被转换成一个 WebGL 小游戏包C# 代码通过 IL2CPP 转成 WASM 或 JS 文件插件层则通过 JSBridge 与微信小游戏的 JS 环境通信。所以接入插屏广告之前你的Unity项目至少要满足三个基本条件项目已经可以成功导出为微信小游戏工程并且能在微信开发者工具里跑通。团结引擎的版本不低于官方对微信小游戏适配的最低要求具体版本去官方文档的更新日志里查不同版本的转换插件API有差异。要有一个可用的微信小游戏 AppID并且该账号已经开通“流量主”功能。其中第二点很多人会忽略。团结引擎的转换插件里不同版本对WX命名空间的封装程度不一样早期版本可能需要自己写.jslib桥接后续版本则提供了比较完整的 C# 侧 API。如果你用的是比较老的 Unity 2020 版本搭配新插件有可能会遇到 API 不存在或参数不匹配的报错这种问题排查起来非常头疼。建议新项目直接用官方推荐的引擎版本和插件版本组合省心很多。2.2 广告位申请与 AppID 绑定插屏广告位要单独申请不是在 Unity 工程里随便写一个广告位 ID 就能用的。操作路径是登录微信公众平台 → 小游戏 → 流量主 → 广告位管理 → 新建广告位 → 选择插屏广告。这一步会生成一个以adunit-开头的广告位 ID后续在 C# 代码里填入的就是这个 ID。需要注意一个容易踩的坑申请广告位时有两种选择和“小程序”是类似的但小游戏端在绑定 AppID 的时候要确认你当前登录的公众平台账号和 Unity 转换设置里填写的 AppID 是同一个。我之前就遇到过 Unity 工程里填了测试 AppID但广告位是在正式 AppID 下申请的结果真机预览时广告怎么都拉取不出来后台的错误日志提示“广告位未绑定当前AppID”。这个错误一般不会第一时间想到白白排查了半天。如果你是首次接入微信提供了测试广告位 ID用于在开发阶段模拟展示。测试广告位的典型格式类似adunit-xxxxxxxxxxxx具体 ID 以当前微信小游戏官方文档为准。测试广告位的价值在于它不受流量主开通状态下线、无真实计费可以随时在开发者工具和真机里验证接入逻辑。2.3 开发者工具与真机预览的差异关于插屏广告测试有一点很关键微信开发者工具里模拟器并不能 100% 还原插屏广告的展示效果尤其是广告素材的拉取和点击跳转行为经常在开发者工具里是空白或静态图真机上才是可点击的交互广告。所以在开发阶段不要因为开发者工具里看不到广告就觉得接入失败了直接用“预览”二维码到真机上测试更靠谱。另外开发者工具里如果开了“模拟无广告”或错误设置了缓存策略也容易导致广告加载失败。我在真机调试时习惯用wx.setEnableDebug或微信开发者工具里的 vConsole 查看日志这样能更直观地看到onError回调里的错误码。3. 核心接入流程与代码实现3.1 从 C# 到微信 JS API 的调用链路在团结引擎里接入插屏广告核心是调用微信小游戏环境提供的 JS 接口。Unity 侧的 C# 代码不能直接调用wx.createInterstitialAd必须通过适配层提供的桥接方法。团结引擎的微信小游戏转换插件会封装好这一层你可以直接用类似WX.CreateInterstitialAd()的方式操作也可以自己写jslib桥接文件。我建议直接使用官方封装因为自己写桥接的话还要处理参数传递和回调线程问题。官方封装好的 API 一般会把 JS 侧的回调事件统一派发到 Unity 主线程这非常重要因为 Unity 的 API 大部分必须在主线程调用如果回调是在子线程触发的调用Debug.Log还没什么大问题但如果直接操作 GameObject 或 UI就会触发UnityException。网上有人分享过自建桥接方案核心思路是在jslib中声明方法然后在 C# 中用DllImport引入。这种做法适合深度定制场景但如果你只是想接插屏广告直接用封装好的接口更省事。我在项目里维护了一个广告管理类所有广告相关逻辑都走这个类方便统一管理和加日志。3.2 插屏广告管理类封装下面这段代码是我在项目里实际使用的广告管理类的精简版本去掉了内部统计逻辑保留了核心接入逻辑。它同时管理插屏广告的创建、加载和展示。using System; using UnityEngine; public class InterstitialAdManager : MonoBehaviour { private static InterstitialAdManager _instance; public static InterstitialAdManager Instance _instance; [SerializeField] private string interstitialAdUnitId adunit-xxxxxxxxxxxx; // 模拟微信插屏广告对象 private object _interstitialAd; private bool _isLoaded; private bool _isShowing; private void Awake() { _instance this; } private void Start() { InitInterstitialAd(); } private void InitInterstitialAd() { // 这里的 WX 类是团结引擎转换插件封装的入口 // 如果插件没有提供需要自行通过 jslib 桥接 // 以下为伪代码示意实际 API 以你使用的插件版本为准 #if UNITY_WECHAT_GAME _interstitialAd WX.CreateInterstitialAd(new WXInterstitialAdParam { adUnitId interstitialAdUnitId }); // 监听加载成功 WX.OnInterstitialAdLoad(() { _isLoaded true; Debug.Log([Ad] 插屏广告加载成功); }); // 监听加载失败 WX.OnInterstitialAdError((string errMsg) { _isLoaded false; Debug.LogError([Ad] 插屏广告加载失败: errMsg); }); // 监听关闭 WX.OnInterstitialAdClose(() { _isLoaded false; _isShowing false; Debug.Log([Ad] 插屏广告已关闭); }); // 首次预加载 LoadAd(); #endif } public void LoadAd() { if (!_isShowing !_isLoaded) { Debug.Log([Ad] 开始加载插屏广告); #if UNITY_WECHAT_GAME WX.LoadInterstitialAd(); #endif } } public void ShowAd() { if (_isLoaded) { Debug.Log([Ad] 展示插屏广告); #if UNITY_WECHAT_GAME _isShowing true; WX.ShowInterstitialAd(); #endif } else { Debug.Log([Ad] 插屏广告未加载无法展示); // 展示失败时重新加载一次方便下次展示 LoadAd(); } } }需要注意不同版本的团结引擎插件WX类的具体接口名可能不同。有的版本是WX.CreateInterstitialAd有的版本是WXInterstitialAd.Create所以在写代码之前先到插件包内部看一下封装好的接口定义或者参考插件自带的 Demo。千万不要照着文档敲完代码发现编译报错再来怀疑人生先确认 API 再写逻辑。3.3 代码里的两个关键细节第一广告对象建议只创建一次。有些开发者会在每次需要展示时重新调用CreateInterstitialAd这在原生小程序里可能问题不大但在 Unity 转小游戏的环境里频繁创建对象会造成不必要的内存开销和 JS 侧资源浪费。我的做法是在管理器初始化时创建一次之后只反复Load和Show。第二合理使用_isShowing标记。插屏广告在展示过程中如果用户又触发了展示逻辑会出现叠加展示的问题。某些微信版本下当插屏已经展示时再次调用show()可能只是返回一个失败 Promise但体验上会出现闪烁或卡顿。加上_isShowing判断后可以在展示期间把所有触发请求全部忽略这是保证体验的基本手段。3.4 加载与展示的时序控制插屏广告有明确的预加载机制。在原生微信小游戏里创建广告实例后需要主动调用一次load()才能让广告素材进入待展示状态。展示之后广告实例会回到未加载状态需要再次load()才能为下一次展示做准备。Unity 侧的逻辑要做到两点游戏启动进入主界面后立刻创建并预加载广告插屏关闭后立即预加载下一次广告。这样可以尽量保证广告在需要展示时是准备好的减少因广告未加载而漏掉展示机会的情况。按照微信广告团队的统计口径展示成功一次之后再预加载下一轮展示的填充率会更稳定。这里的本质原因是广告请求是异步的展示时机不可控而预加载把时间不确定性和用户行为之间做了一个缓冲。4. 展示时机和频率控制4.1 展示时机选择的原则插屏广告如果出现在用户正专注于操作的时候那用户体验一定崩。我的经验是插屏展示必须绑在“自然停顿点”上。在休闲游戏里这类停顿点一般包括关卡失败后的重试弹窗之前关卡成功结算后、点“下一关”之前从游戏返回主界面的瞬间暂停菜单呼出时长时间停留在一个静态页面的第30秒左右如设置页、商城页。其中效果最稳定的是“关卡结束回到主界面”的节点。这时候用户处于一个操作空档期注意力已经从紧张的关卡中抽离出来对广告的容忍度最高。相比之下“游戏刚开始1秒就弹插屏”几乎是所有用户骂声的来源这种触发时机我强烈建议不要在正式版本里出现。从技术层面来说选择这些节点还有一个好处就是它们都是“用户主动行为”而不是“时间回调”。基于时间回调的插屏展示比如每60秒弹一次很容易在用户正在拖拽摇杆时弹出造成误触和反感。而基于行为的展示天然和用户节奏匹配这也是微信广告官方推荐的触发方式。4.2 频控策略和逻辑实现微信平台对插屏广告本身有频控限制但开发者也要在业务层自己做频控。常见做法是记录两次展示之间的时间间隔设置一个最短冷却时间。我自己的默认策略是两次插屏展示之间至少间隔60秒并且单日同一用户最多展示6次。这里没有统一的“最佳值”需要根据游戏实际时长和关卡节奏调整。休闲游戏用户可能一天玩几十关如果不做频控一天弹几十次广告收益短期上去了但用户的次留和时长必然掉得厉害。频控逻辑和真实代码可以这样做public class AdFrequencyController { private const float MIN_INTERVAL 60f; private const int DAILY_MAX_IMPRESSIONS 6; private float _lastShowTime -999f; private int _dailyShownCount 0; private string _currentDate ; public bool CanShow() { RefreshDailyCount(); bool timeOk Time.time - _lastShowTime MIN_INTERVAL; bool countOk _dailyShownCount DAILY_MAX_IMPRESSIONS; return timeOk countOk; } public void OnAdShown() { _lastShowTime Time.time; _dailyShownCount; } private void RefreshDailyCount() { string nowDate DateTime.Now.ToString(yyyy-MM-dd); if (nowDate ! _currentDate) { _currentDate nowDate; _dailyShownCount 0; } } }这段逻辑的关键在于CanShow()和OnAdShown()必须成对出现不能只调用CanShow()然后广告展示失败就不管了。如果展示失败这不算一次有效展示所以OnAdShown()应该在广告成功展示之后再调用而不是在触发点击时调用。4.3 从数据角度调整频控参数只知道“限制次数”还不够上线第一周建议每天看三个指标插屏展示次数、点击率、人均展示次数。如果人均展示次数超过了每日上限说明你的频控代码没有生效或者用户触发的展示节点过于集中如果点击率极低低于0.5%说明广告展示的位置用户根本不看或者素材和用户群体不匹配。有一个容易被忽略的细节微信后台的“频控”是以广告位为维度的如果你在同一个游戏里创建了多个插屏广告位并都展示每个广告位会各自拉取广告这会导致同一个用户一天看到更多次插屏即使每个广告位的频控都正常。我一般建议一个游戏只使用一个插屏广告位通过代码逻辑控制展示次数反而更容易管理。5. 线上常见问题与排查记录5.1 插屏广告无法加载或一直显示空白这个问题出现频率最高。处理思路可以按顺序排查确认广告位 ID 是否有效是否被平台封禁或审核中确认当前微信版本是否支持插屏广告部分老旧版本基础库不支持查看onError回调的错误码和错误信息使用微信开发者工具的真机调试进行验证注意工具模拟器和真机的差异。在我的经验里最常见的原因是开发阶段用了测试广告位但代码上传后没有切换成正式广告位。由于测试广告位的填充率有限线上真实用户访问时广告加载就会明显变慢甚至经常加载失败。解决方法是把广告位 ID 放到一个配置文件里开发打包时自动替换成测试 ID正式构建时替换成正式 ID避免人肉切换的错误。5.2 show 失败或 show 调用无反应如果插屏广告已经加载成功但调用show()没有任何反应或者返回fail一般有三类原因展示频率超出了平台限制微信平台对同一用户展示频次有限流短时间内频繁请求会失败正在展示其他广告组件如激励视频、banner、原生模板插屏与某些广告类型互斥广告位所在页面栈为空或者处于不适配的页面场景展示时机不对。针对第一类除了靠平台限流我们还要自己做好频控也就是上一节讲的那个控制器。针对第二类我在分包加载和激励视频回调里都做了标志位判断确保同一时刻只有一个广告组件在展示。这是因为微信小游戏环境里视频广告和插屏广告同时展示很可能会导致其中一个直接黑屏。5.3 广告关闭后游戏状态恢复异常插屏广告显示和关闭时用户的注意力会从游戏切走游戏本身可能被系统挂起或播放被打断。Unity 里常见的表现是广告关闭后游戏音量恢复异常、Time.timeScale 没有重置、音频播放继续但画面卡住。这个问题要从两个维度解决。第一在广告展示前暂停游戏逻辑。如果是用Time.timeScale 0的方式暂停需要记下暂停前的值在广告关闭后恢复如果游戏里有一堆协程和物理模拟推荐用“游戏状态枚举”的方式做暂停而不是单纯依赖timeScale。第二在广告关闭回调里统一调用一个恢复函数。这个恢复函数负责重置timeScale、恢复音频监听器、刷新 UI 状态。如果是插屏遮挡了 UI 导致点击穿透还要在展示前隐藏某些按钮或加遮罩。我遇到过一种特殊情况插屏展示时游戏因为内存压力被系统回收回到游戏时场景已经重新加载了如果广告管理类是挂在场景对象上的那广告对象就丢失了。这种情况下恢复函数要能把广告管理器重建出来并重新预加载。所以广告管理器尽量不要做成场景内对象可以考虑挂在一个跨场景的常驻节点上或者用单例模式保证全局唯一。5.4 审核与隐私合规相关注意事项微信小游戏在上线审核时广告相关功能是需要明确说明的。特别是隐私保护指引里要声明会收集设备标识信息用于广告投放。这个在公众平台后台填写时容易漏掉漏掉的结果就是线上版本广告展示被限制或直接审核不通过。团结引擎转换出来的小游戏包里如果代码里调用了广告相关 API平台审核时会检查代码里是否有createInterstitialAd等调用同时检查后台是否配置了对应权限。如果后台和代码不同步就可能出现“审核不通过”或“线上广告不可用”。我在提审前都会做一个自查清单后台广告位状态正常、隐私协议已更新、体验版真机广告可正常展示、广告位 ID 是正式 ID。5.5 常见问题速查表现象可能原因排查手段与解决思路开发者工具里无广告工具模拟器限制直接用真机预览验证以真机行为为准真机加载失败广告位ID错误、AppID不匹配检查广告位ID与AppID是否属于同一账号展示触发未弹广告频控拦截、项目状态标志位异常加日志确认CanShow()和_isLoaded状态show失败且Promise抛错平台限流、展示互斥延迟3~5秒后重新预加载避免连续调用广告关闭后游戏卡死Time.timeScale未恢复在关闭回调中重置时标并恢复音频监听器点击广告跳转后游戏崩溃生命周期切换未处理在OnApplicationPause/OnApplicationFocus中做状态保存这张表看着简单但每一条背后都有一个真实的线上事故。尤其是“点击广告跳转后游戏崩溃”这个问题在处理视频广告时我遇到过后来排查才发现是跳转打开外部页面时Unity 的OnDestroy被误触发导致全局数据被清空。处理手段是在广告跳转事件里设置一个“忽略销毁标记”避免清理关键数据。6. 最后再分享一个调优技巧插屏广告接入本身并不难难的是“数据稳定”。我每次上线新版本后都会先小流量发布用3到7天的时间看插屏相关数据再决定是否全量开放。在这个阶段我会把广告展示频控的数值调得保守一些比如间隔调成90秒、每日上限调成4次宁可少赚一点也要先保证用户不因为广告产生负面反馈。等数据确认稳定后再逐步放宽频控参数。另外不要忽视广告位的“类型选择”。微信的插屏广告目前有多种样式有的偏图片有的偏视频。不同样式的填充率、eCPM和用户点击率差异很大。可以在后台多创建几个备选广告位用 A/B 测试的方式对比数据选择最优的样式作为主广告位。这个操作不影响 Unity 代码只需要在广告位 ID 层面切换即可。如果你在接入过程中遇到什么奇怪的问题比如某个安卓机型上插屏一直拉取失败而其他机型正常这类问题通常和微信版本、机型兼容性有关也遇到过几次。把机型日志和错误码抓下来提交给微信广告平台的技术支持基本都能解决。不要自己在代码里写一堆针对特定机型的 hack那样只会让你的代码越来越难维护。
阅读完成 · 觉得有帮助?