跳到主要内容

广告接入实现(Cocos Creator)

这篇回答什么问题: 用 Cocos Creator 做微信 / 抖音小游戏,广告从创建、预加载、展示到发奖这条链路怎么写才不漏收入、不出漏洞,以及两端 API 到底哪里不一样。

前置:广告位设计与 IPU 优化 讲摆在哪,本文只讲怎么接对。摆错位置是效率问题,接错链路是收入问题——后者更贵。

零、先认清一件事:Cocos 不封装广告​

Cocos Creator 3.8 的微信小游戏发布文档明确写着,平台 SDK(用户、社交、支付等)「移植工作在现阶段还是需要开发者自己处理」。

来源:Cocos Creator 3.8 用户手册 · 发布到微信小游戏(采集:2026-10-28)

这句话的推论很实际:

  • 代码里会直接出现 wx. / tt.,TypeScript 不认识这两个全局对象,得自己写声明文件,否则整个项目编译不过
  • 任何「装个插件就有广告 API」的教程都要留一手——插件多半只是套了一层壳,底下的坑一个不少
  • 双端差异必须自己抹平,没有官方中间层兜底

声明文件最小写法(放到 assets/scripts/types/ 下):

assets/scripts/types/platform.d.ts
declare const wx: any;
declare const tt: any;

不要为了「类型安全」去手写完整的 RewardedVideoAd 接口。平台接口会加字段(下面 2.5 的 count 就是例子),类型写死之后每次升级都要跟着改,成本大于收益。

一、两端广告 API 对照表​

以下全部来自官方文档,采集日期 2026-10-28,逐条可查(见文末来源表)。

能力微信抖音关键差异
激励视频wx.createRewardedVideoAd({adUnitId})tt.createRewardedVideoAd({adUnitId})加载链路相反,见 2.1
插屏wx.createInterstitialAd({adUnitId})tt.createInterstitialAd({adUnitId})实例生命周期完全不同,见 2.2
原生模板 / 横幅wx.createCustomAd({...})tt.createBannerAd({...})微信 Banner 已停维护,见 2.4
关闭回调onClose(res) → res.isEndedonClose(res) → res.isEnded + res.count见 2.5
激励视频最低基础库2.0.41.3.0—
插屏最低基础库2.6.01.71.0—
原生模板最低基础库2.11.1——

微信侧还支持 multiton: true(2.8.0 起,多例模式)和 disableFallbackSharePage(3.7.7 起,禁用分享页),抖音侧对应的是「激励再得」,参数名和玩法都不一样。

二、五个不对称点​

这一节是本文的核心。下面每一条都是「按一个平台写、到另一个平台就废」的地方。

2.1 激励视频:加载链路是反的​

微信:create → load() 预加载 → onLoad 之后才 show()。load() 返回 Promise,是官方给的预加载手段。

抖音:官方明确要求不要走这条路。原文大意是——

  • 广告创建后可以在用户操作时直接调 show(),不需要再次 load()
  • 建议直接 show,不要用 load → 触发 onLoad → show 的链路
  • 第一次 createRewardedVideoAd() 创建对象后,不会抛出任何事件,目前也不会自动加载

来源:抖音 · 激励视频广告(采集:2026-10-28)

于是最经典的翻车写法:

// ❌ 在抖音上大概率永远等不到 onLoad
const ad = tt.createRewardedVideoAd({ adUnitId });
ad.onLoad(() => ad.show());
这不是「稍微慢一点」,是「一次都不出」

微信上必须等加载完再 show,抖音上创建后直接 show 就对了。一套代码统一写成「等 onLoad 再 show」,结果就是微信正常、抖音零展示——而抖音的收入报表要等上线后才可见,你在测试环境根本发现不了。

正确做法是在平台层各写各的,不要抽公共的加载流程。抽象层次提到「给广告位 id,返回是否发奖」,加载细节留在各自实现里。

2.2 插屏:微信实例可复用,抖音实例用一次就死​

微信:createInterstitialAd 每次调用返回全新实例。官方只写了两条约束——「每次创建都会返回一个全新的实例」和「插屏广告实例不允许跨页面使用」,没写「只能展示一次」。所以同一页面内可以缓存复用,但不能跨页面缓存。

来源:微信 · wx.createInterstitialAd / InterstitialAd 类(采集:2026-10-28)

「不允许跨页面使用」这条在 Cocos 里容易踩到:如果把它理解成「游戏只有一个场景」,就不会出问题;但只要用了多场景(director.loadScene),上一个场景缓存的实例在新场景里就是无效的,show() 不起作用也不报错。插屏实例应当按场景持有,离开场景时销毁。

抖音:每次创建返回全新实例,且实例只支持展示一次——加载出错、展示成功、点击关闭,三种情况都会自动销毁,下次必须重新创建。

来源:抖音 tt.createInterstitialAd 及其 C-API 说明页(采集:2026-10-28)

这条差异的杀伤力在缓存上。下面这种写法在微信上完全没问题,在抖音上第二次调用就静默失败:

// ❌ 抖音上只对第一次有效
let interstitial = null;
function showInterstitial(id) {
if (!interstitial) interstitial = tt.createInterstitialAd({ adUnitId: id });
interstitial.show();
}

抖音侧必须每次新建:

// ✅ 抖音插屏:一次一个实例,用完即弃
function showInterstitial(adUnitId: string): Promise<boolean> {
const ad = tt.createInterstitialAd({ adUnitId });
return new Promise((resolve) => {
ad.onClose(() => resolve(true));
ad.onError(() => resolve(false));
ad.show().catch(() => resolve(false));
});
}

2.3 抖音插屏有三道时间闸门​

抖音插屏的限制分两套口径,数字不一致:

口径启动后插屏间隔与激励视频间隔出处
接口文档 / C-API 页15 秒30 秒(否则报 2002)—tt.createInterstitialAd
小游戏行为规范30 秒60 秒60 秒运营规范 2.2.3
两份官方文档打架,按行为规范执行

接口文档只描述技术限制,行为规范是处罚依据。技术限制拦不住你,处罚拦得住。

所以代码里按 30s / 60s / 60s 配,不要踩 15s / 30s 的线。详见 合规红线 第三节。

2002 的含义是「等待若干秒再请求」,它不是故障。这些闸门直接影响 广告位设计 里的判断:

  • 「进游戏就弹插屏」在抖音上不可行
  • 「连续游玩 N 局后弹」的 N 要按时间算,不能按局数算——一局 10 秒的游戏,N 局可能还不到 60 秒
  • 节流必须做在客户端,不能只靠服务端下发配置。用户连续点击时,客户端是唯一能拦住的地方
别把 2002 当错误上报

把它塞进 onError 的失败率统计,你会看到一个虚高的「广告失败率」,然后去查根本不存在的网络问题。插屏要先在本地判时间,够条件才发请求。

2.4 微信的 Banner 已经停维护了​

微信从基础库 3.5.5 起停止维护 wx.createBannerAd,官方要求改用 wx.createCustomAd(原生模板广告,2.11.1 起支持)。

来源:微信 · wx.createBannerAd、wx.createCustomAd(采集:2026-10-28)

两个 API 的参数不一样,照抄会报错:

参数BannerAdCustomAd
adUnitId必填必填
adIntervals选填,≥30 秒,不传则不自动刷新必填,≥30 秒,仅对支持自动刷新的模板生效
style.left / top必填必填
style.width必填仅某些模板生效(如矩阵格子)
style.height必填不存在
style.fixed无仅小程序有效,小游戏传了无效

注意 style.height 在 CustomAd 里没有——原生模板的高度由模板自己决定,你控制不了。这意味着不能再用「预留 90px 高度」的方式给横幅留位置,得按模板实际返回的尺寸做布局,否则会盖住操作区。

2.5 关闭回调字段不同,抖音多一个 count​

微信:onClose(res) 只保证 res.isEnded(2.1.0 起),含义是「视频是否是在用户完整观看的情况下被关闭的」。

抖音:onClose(res) 有 res.isEnded 和 res.count 两个字段。count 表示用户完整观看了几次,官方建议「在返回 count 的情况下,统一使用该字段判断广告是否观看完成」。

来源:抖音 · RewardedVideoAd.onClose(采集:2026-10-28)

所以统一封装的返回值必须能吃下「看了几次」这个概念,而不是 boolean:

interface AdResult {
/** 本次应当发几份奖励。0 表示不发 */
rewardCount: number;
/** 展示是否成功(含失败重试成功的) */
shown: boolean;
error?: string;
}

现在只用得上 0 和 1,但抖音的「激励再得」一旦开启,一次 onClose 可能返回 count: 3——按 boolean 写的代码到那天要重写发奖逻辑。这是提前留一个字段的成本,几乎为零。

抖音「激励再得」相关参数(multitonRewardMsg / multitonRewardTimes / progressTip)目前仅支持安卓,接入时要用 tt.getSystemInfo 分流。

三、发奖链路:三个必踩的坑​

3.1 发奖只能在 onClose 里​

show() 返回的 Promise 在广告开始播放时 resolve,而不是播放结束时。这个时机差别在桌面模拟器上看不出来,真机上第一次测就会暴露。

在 await show() 之后发奖,等于送钱
// ❌ 用户刚看到广告第一帧就拿到奖励,然后可以立刻关掉
await ad.show();
grantReward();
// ✅ 唯一正确的发奖时机
ad.onClose((res) => {
if (res.isEnded) grantReward();
});

3.2 单飞锁:一条广告只能发一份奖​

看一次广告拿三次奖励,是 IAA 最经典的线上事故,成因有三个,而且经常同时出现:

  1. onClose 是持续监听,不是一次性回调。在 show() 里重复注册,回调会一路累积
  2. show() 失败后重试,同一局的结算函数被挂了两遍
  3. 用户连点按钮,两次 show() 竞争同一个实例

解法只有一个:同一时刻只允许一局在播,用一个 pending 变量同时承担「当前这一局的结算函数」和「是否有局在播」两个语义。

scripts/platform/adManager.ts(示意)
let pending: ((r: AdResult) => void) | null = null;

function settle(r: AdResult) {
const fn = pending;
pending = null; // 先清锁,再回调 —— 顺序不能反
fn && fn(r); // fn 只可能被调用一次
}

「先清锁再回调」这个顺序很关键。反过来写,回调里如果又触发了一次播放(比如奖励到手后立刻引导看下一次),新的一局会被这把还没清掉的锁挡掉。

3.3 isEnded 不等于可信​

res.isEnded 是客户端返回值。改包、跑模拟器、直接调 grantReward() 都能绕过它。

  • 低价值奖励(复活、双倍金币):客户端判断够了,加个服务端频次上限就行
  • 高价值奖励(稀有道具、大额货币):必须服务端校验。小游戏没有账号体系时至少做两件事——奖励发放走服务端接口、按设备与账号维度限制单日总量

这是判断,不是平台规则。但对纯 IAA 产品,超发一次稀有道具对经济系统的伤害,可能大于那一天的全部广告收入。

四、加载与失败降级​

4.1 预加载时机​

平台创建预加载播放后
微信首次进入游戏时load(),onLoad 后置 ready 标记立刻重新 load(),否则下一次拿不到广告
抖音首次需要时不需要,直接 show()视实例策略而定,见下

微信侧「播放完要重新 load」这条,漏了不会报错,只会表现为第二次点击广告没反应。测试时连着点两次就能发现,但只点一次就上线的话永远发现不了。

抖音侧实例是否需要每次重建,官方文档未明确说明(示例代码是创建一次、监听一次)。本站暂按「复用实例」实现,同时保留 destroy() 兜底,列为待核实。

4.2 onError 要分四类,别一律当失败​

类型典型错误处理
无填充该地区/时段没有广告可投静默降级,走免费奖励分支
网络超时弱网重试一次,仍失败则降级
实例失效长时间切后台重建实例后再试一次
参数错误adUnitId 填错 / 广告位未审核通过必须报错到控制台并上报,禁止静默降级

最后一类是最贵的。adUnitId 填错、广告位没通过审核、用了测试 id,表现都是「广告一直出不来」——如果代码把它当普通失败吞掉,你会带着一个零收入的包上线,而所有页面都正常、没有任何报错。

上线前的硬检查

正式包里所有 adUnitId 必须逐条核对平台后台,且开发期必须有一个开关能让错误直接抛出来。测试环境的广告失败率永远偏高,别把「测试时也出不来」当成正常现象。

4.3 降级路径:不是取舍题​

广告拉不到时,用户在等一个结果。两种处理各有代价:

策略用户感受收入影响适用
免费发奖好,「系统送的」这次少一份收入,但保住体验A 类(用户主动要的)
静默跳过,流程继续无感保住单价B / C 类
弹窗提示「稍后重试」差,尤其失败复活场景保住单价,但用户可能直接退出不要用

判断依据是 广告位设计 里的分档:A 类广告失败必须给免费奖励,因为用户是在最需要帮助的时刻被拒绝的;C 类插屏失败直接跳过。

这条不只是体验选择,抖音把它写成了硬规定

抖音《广告小游戏运营规范》明确:没有对广告不展示等异常情况做兜底处理、导致用户行为中断的,属于违规。原文要求「如不支持激励视频的低版本用户、广告调用失败等情况,应直接展示结果或给予奖励」。

所以「提示稍后重试」这种让用户卡在原地的写法,在抖音上不只是转化差,是可能被判违规。详见 合规红线 3.3 节。

五、包体与首屏:广告还没露脸,人就走了​

微信小游戏主包不能超过 4MB,包含所有代码和资源,额外资源必须走网络下载。

来源:Cocos Creator 3.8 用户手册 · 发布到微信小游戏(采集:2026-10-28)

分包的四条上限(来源:微信开放文档 · 分包加载,采集:2026-10-28):

限制项上限
主包4MB
全部主包 + 分包总和30MB
单个普通分包不限制
单个独立分包4MB
总上限是 30MB,不是 20MB

网上大量教程和部分英文版文档仍写「总大小 20M」——那是扩容前的旧数字。中文官方页现已写 30M。

这条影响的是「能不能做重度」:30MB 意味着可以做有一定美术体量的产品,20MB 则基本只能做超休闲。规划资源量时按 30MB 算,但主包 4MB 这条没变,所以分包策略仍然是第一优先级。

同页还有一条更容易被忽略的限制:小游戏包内资源不是按需加载,而是一次性加载完所有包内资源再启动页面。所以主包里每多 100KB,都在直接拖慢每一个用户的首次启动——不管这个资源这一局用不用得上。

另外两条硬约束:

  • 不可以从远程服务器下载脚本文件(资源可以,脚本不行)
  • 微信小游戏不支持 WebView

降低主包的三个手段,都在 Cocos 构建面板里:

手段作用注意
初始场景分包(startSceneAssetBundle)首场景及依赖进 assets/start-scene,本地加载主包放远程时必须开,否则首屏要等下载
引擎原生代码分包引擎的 WASM/Asm.js 进子包减少主包体积
分离引擎(separateEngine)用微信小游戏引擎插件仅支持 js 模式,开了 WASM 物理就不能用

为什么这条要写在广告文档里:广告的机会窗口是前 3 分钟(见 广告位设计 第七节)。首屏慢 2 秒,用户在那 3 分钟里能走到的关卡就少一关,A 类广告的触点直接就少一个。包体问题最后一定以 IPU 的形式体现在报表上。

六、一套代码跑两端:隔离层怎么写​

6.1 目录结构​

assets/scripts/
platform/
types.ts # 统一接口与返回类型
wechat.ts # wx.* 实现
douyin.ts # tt.* 实现
index.ts # 按平台导出,业务层只 import 这里
game/ # 业务逻辑,不允许出现 wx./tt.

规矩只有一条:game/ 目录下不许出现 wx. 或 tt.。 出现了就意味着以后加第三个平台时要改业务代码,那时候的改动量是现在的十倍。

6.2 平台判断​

Cocos Creator 3.x 的平台枚举是 sys.Platform,字符串值,微信为 WECHAT_GAME,抖音为 BYTEDANCE_MINI_GAME。

来源:Cocos Creator API · 枚举 Platform(采集:2026-10-28,查的是 3.3 版文档,3.8 未逐项核对,接入时以所装版本的 cc.d.ts 为准)

scripts/platform/index.ts
import { sys } from 'cc';

export type PlatformTag = 'wechat' | 'douyin' | 'web';

export function platformTag(): PlatformTag {
if (sys.platform === sys.Platform.WECHAT_GAME) return 'wechat';
if (sys.platform === sys.Platform.BYTEDANCE_MINI_GAME) return 'douyin';
return 'web'; // 编辑器预览、浏览器调试
}

web 分支必须有,而且要有能跑通同一套流程的假实现(模拟 1.5 秒后返回 isEnded: true)。否则每次调广告都要真机,验证「发奖逻辑对不对」这种纯业务问题会被拖到极慢。

6.3 统一接口​

scripts/platform/types.ts
export type AdType = 'rewarded' | 'interstitial' | 'native';

export interface AdResult {
rewardCount: number; // 0 = 不发奖
shown: boolean;
error?: string;
}

export interface IAdService {
/** 预热,进入可能需要的场景前调用,失败不阻塞 */
preload(type: AdType, zoneId: string): void;
showRewarded(zoneId: string): Promise<AdResult>;
showInterstitial(zoneId: string): Promise<AdResult>;
/** 原生模板/横幅的位置,单位 px,左上角原点 */
layoutNative(zoneId: string, rect: { left: number; top: number; width: number }): void;
}

zoneId 是唯一定位一个广告位的字符串,同时用于三个地方:取 adUnitId、埋点上报、后台频控配置。一个广告位只有一个 zoneId,跨平台也不复用——微信和抖音的广告位是两套后台,同一个逻辑位置有两个物理 id。

6.4 微信侧骨架​

scripts/platform/wechat.ts
import type { AdResult } from './types';

declare const wx: any;

let rewarded: any = null;
let pending: ((r: AdResult) => void) | null = null;

function ensureRewarded(adUnitId: string) {
if (rewarded) return rewarded;
rewarded = wx.createRewardedVideoAd({ adUnitId }); // 小游戏端是全局单例

rewarded.onError((err: any) => {
settle({ rewardCount: 0, shown: false, error: `wx_${err?.errCode ?? 'unknown'}` });
});

rewarded.onClose((res: any) => {
const ended = res?.isEnded === true;
settle({ rewardCount: ended ? 1 : 0, shown: true });
rewarded.load().catch(() => {}); // 看完立刻预热下一次
});

rewarded.load().catch(() => {});
return rewarded;
}

function settle(r: AdResult) {
const fn = pending;
pending = null;
fn && fn(r);
}

export function showRewarded(adUnitId: string): Promise<AdResult> {
if (pending) return Promise.resolve({ rewardCount: 0, shown: false, error: 'busy' });

const ad = ensureRewarded(adUnitId);
return new Promise<AdResult>((resolve) => {
pending = resolve;
ad.show().catch(() => {
// show 失败:load 一次再重试,仍失败才结算
ad.load()
.then(() => ad.show())
.catch(() => settle({ rewardCount: 0, shown: false, error: 'show_failed' }));
});
});
}

注意 onError 里也调了 settle——广告拉取失败时不会触发 onClose,如果只监听 onClose,用户点了按钮之后就一直等在那里,UI 永远转圈。

6.5 抖音侧骨架​

scripts/platform/douyin.ts
import type { AdResult } from './types';

declare const tt: any;

export function showRewarded(adUnitId: string): Promise<AdResult> {
// 抖音:不走 load -> onLoad -> show,创建后直接 show
const ad = tt.createRewardedVideoAd({ adUnitId });

return new Promise<AdResult>((resolve) => {
let settled = false;
const done = (r: AdResult) => {
if (settled) return;
settled = true;
resolve(r);
};

ad.onError((err: any) => done({ rewardCount: 0, shown: false, error: `tt_${err?.errNo}` }));

ad.onClose((res: any) => {
// 官方建议:有 count 时以 count 为准
const count = typeof res?.count === 'number' ? res.count : (res?.isEnded ? 1 : 0);
done({ rewardCount: count, shown: true });
});

ad.show().catch(() => done({ rewardCount: 0, shown: false, error: 'show_failed' }));
});
}

抖音侧每次 show 都新建实例,是否造成实例泄漏未在文档中找到说明,列为待核实。稳妥做法是在 done() 之后调用 ad.destroy && ad.destroy()。

七、埋点:把口径落成事件​

术语与指标口径 里三个核心指标的「数据来源」都写着自建埋点。这一节把这句话补完。

7.1 事件表​

事件触发时机必带字段
ad_request决定要展示一次广告(含预加载)zone_id ad_type scene
ad_showshow() 成功,广告真正露出zone_id ad_type
ad_closeonClose 触发zone_id reward_count watch_ms
ad_erroronError 触发zone_id err_code err_type
ad_reward奖励发放成功zone_id reward_count item_id

公共字段:uid(设备维度匿名 id)、session_id、platform、day_n(用户第几天)、ts(服务器校准后时间戳)、ver(包版本)。

7.2 三条必须守住的规矩​

request 和 show 不能合并。 合并了就算不出展示率,而展示率正是 glossary 里判断「平台没广告」还是「你自己没露出来」的唯一依据。

zone_id 一个都不能少。 没有 zone 维度,加完第二个广告位之后就再也无法归因是哪个位在赚钱。这是 IAA 埋点最常见的偷懒,代价在三个月后才显现。

切后台会丢包。 小游戏被切走时网络请求可能直接中断。上报要么走本地缓冲 + 下次启动补发,要么接受 ad_close 的丢失率——但必须知道丢了,否则 ad_show - ad_close 的差值会被误读成「用户看完不回来」。

7.3 与平台后台对账​

平台后台的收入 ÷ 你埋点的展示数 × 1000 = 你的实际 eCPM。这个数字和后台显示的 eCPM 一定对不上,差值通常来自三处:有效展示口径、分成前后、时区。

对账频率建议每周一次,看趋势比值而不是绝对值。比值突然跳变(比如某周实际 eCPM 掉了 30%),要么是广告位配置被改,要么是埋点少报了展示——后者会伪装成「收入下降」,实际是数据问题。

八、上线前自查表​

  • 所有 adUnitId 已逐条核对平台后台,没有残留测试 id
  • 参数错误(广告位无效)会抛错并上报,不会被当成普通失败吞掉
  • 发奖只发生在 onClose 内,show() 的 then 里没有任何发奖代码
  • 有单飞锁,连点按钮不会发起第二次播放
  • onClose / onError 只注册一次,没有在 show() 里重复注册
  • 微信侧播放结束后会重新 load()
  • 抖音侧没有使用 load → onLoad → show 链路
  • 抖音插屏每次新建实例,且做了「启动 30 秒 / 间隔 60 秒 / 距激励视频 60 秒」本地节流
  • 抖音 onClose 用 count 判断,代码能处理 count > 1
  • 微信横幅用的是 createCustomAd,布局不依赖固定高度
  • 广告失败时有明确的降级分支,A 类有免费奖励兜底
  • 主包 ≤ 4MB,构建时看过实际体积
  • 首次启动到第一帧的耗时在真机上量过(低端安卓机)
  • web 分支有假实现,编辑器里能跑通完整发奖流程
  • 每个广告位都有 zone_id,五个事件都上报了

九、常见错误清单​

  1. 统一写「等 onLoad 再 show」。微信对,抖音错,且错得安静——抖音零展示不会报错。
  2. 缓存抖音插屏实例。实例展示一次就销毁,第二次调用失败没人发现。
  3. 把 2002 当网络错误上报。失败率虚高,然后去修一个不存在的问题。
  4. 在 await show() 之后发奖。桌面模拟器看不出来,真机必现。
  5. onClose 注册在 show() 里。回调累积,看一次发三次。
  6. 只监听 onClose 不监听 onError。广告拉不到时按钮永远转圈。
  7. adUnitId 填错被静默降级。带着零收入的包上线,所有页面都「正常」。
  8. 埋点合并 request 与 show。展示率从此算不出来,排查广告问题没有依据。
  9. 业务代码里直接写 wx.。加第二个平台时全面返工。
  10. 只测「看完」不测「中途关闭」。两种路径的分支逻辑完全不同,前者正常不代表后者正常。

十、待核实​

  • 抖音插屏闸门的最终口径:接口文档 15s/30s 与行为规范 30s/60s 并存,本站取严按 30s/60s/60s 执行,建议向直客或工单确认
  • 微信 InterstitialAd 能否多次 show() → 已核实:官方未限制展示次数,但明确「实例不允许跨页面使用」。同一场景内可复用,跨场景必须重建,见 2.2
  • 微信分包总大小上限 → 已核实为 30MB(主包 4MB / 普通分包不限 / 独立分包 4MB),见第五节
  • 抖音小游戏的包体限制 → 已核到部分:网易 Unity 方案首包 < 60MB、Wasm 方案首包 < 30MB(接入指引)。Cocos 原生方案的具体上限官方未单列,实际以开发者工具上传报错为准
  • 抖音激励视频实例是否需要每次重建,复用是否存在泄漏
  • 抖音 count 字段在未开启多例模式时的实际返回值(官方称「与 multiton 是否为 true 无关」,需实测)
  • Cocos 3.8 的 sys.Platform 枚举是否与 3.3 文档完全一致(未逐项核对)

待补充​

  • 微信小游戏「高性能模式」对广告组件层级的影响(真机验证)
  • 广告组件与 Cocos 渲染层的层级冲突处理(原生组件永远在 Canvas 之上)
  • 安全区的具体实现:wx.getSystemInfoSync().safeArea 在两端字段是否一致
  • 各品类实测的展示率、填充率区间(需真实数据)

来源​

事实数值 / 结论来源采集日期等级
Cocos 不封装平台 SDK移植工作需开发者自行处理Cocos 3.8 · 发布到微信小游戏2026-10-28A
微信小游戏主包上限4MB同上2026-10-28A(Cocos 文档口径)
包内资源加载方式一次性加载,非按需同上2026-10-28A
不支持远程下载脚本是同上2026-10-28A
分离引擎限制仅支持 js 模式同上2026-10-28A
微信激励视频最低基础库2.0.4,小游戏端全局单例微信 · wx.createRewardedVideoAd2026-10-28A
微信激励视频可选参数multiton 2.8.0、disableFallbackSharePage 3.7.7同上2026-10-28A
微信 onClose.isEnded2.1.0 起,含义为「是否完整观看后关闭」微信 · RewardedVideoAd.onClose2026-10-28A
微信插屏最低基础库2.6.0,每次创建返回全新实例微信 · wx.createInterstitialAd2026-10-28A
微信插屏实例作用域实例不允许跨页面使用微信 · InterstitialAd 类2026-10-28A
微信分包上限主包 4MB / 总和 30MB / 普通分包不限 / 独立分包 4MB微信 · 分包加载2026-10-28A
微信 Banner 停维护3.5.5 起,改用 wx.createCustomAd微信 · wx.createBannerAd2026-10-28A
微信 CustomAd 参数2.11.1 起;adIntervals 必填;style.width 部分模板生效;无 style.height微信 · wx.createCustomAd2026-10-28A
抖音加载链路建议直接 show,不走 load → onLoad → show;首次创建不抛事件、不自动加载抖音 · 激励视频广告2026-10-28A
抖音 onClose 字段isEnded + count,官方建议有 count 时用 count抖音 · RewardedVideoAd.onClose2026-10-28A
抖音激励再得参数multitonRewardMsg / multitonRewardTimes / progressTip,仅安卓抖音 · 商业化激励再得2026-10-28A
抖音插屏基础库1.71.0,每次创建新实例抖音 · tt.createInterstitialAd2026-10-28A
抖音插屏 2002需等 30 秒后再请求同上2026-10-28A
抖音插屏时间闸门(接口层)启动 15s 内不可展示;间隔 ≥30s;实例仅可展示一次抖音 · 插屏广告 C-API2026-10-28B(C-API 页,JS 端未重复说明)
抖音插屏时间闸门(运营层)启动 30s 内不可展示;插屏间隔 60s;距激励视频 60s抖音 · 小游戏行为规范2026-10-28A(与上一行冲突,取严)
广告失败须兜底应直接展示结果或给予奖励抖音 · 广告小游戏运营规范2026-10-28A
Cocos 平台枚举sys.Platform.WECHAT_GAME / BYTEDANCE_MINI_GAMECocos API · 枚举 Platform2026-10-28B(3.3 版文档)
show() 的 Promise resolve 时机开始播放时,非播放结束无官方明文,实践中确认—C(判断,需真机验证)

等级说明: A = 官方文档明确写出;B = 官方文档的旧版页或相邻能力页,需复核;C = 经验判断,未经文档证实。

变更记录​

日期变更
2026-10-28建立初版。确定以 Cocos Creator 为目标引擎,双端 API 差异按 2026-10-28 官方文档核对
2026-10-28修正:抖音插屏闸门原按接口文档 15s/30s 写入,后发现《小游戏行为规范》要求 30s/60s/60s 且为处罚依据,全文改为取严口径;4.3 降级策略由「可选」改为「不可中断用户流程」(抖音运营规范硬要求)
2026-10-28核实补充:微信分包总上限确认为 30MB(原待核实);微信插屏实例补「不允许跨页面使用」约束,并给出多场景下的持有建议。两条待核实项关闭

相关文档: 广告位设计与 IPU 优化(摆在哪)· 合规红线(什么动作会被罚)· 术语与指标口径(埋点要对的账)· 平台与变现渠道(广告位怎么开通)