t1k:cocos:playable:build-size
| Field | Value |
|---|---|
| Module | playable |
| Version | 2.14.4 |
| Effort | high |
| Tools | — |
Keywords: build size, engine module, FBX, glTF, mesh compress, meshopt, model compression, optimization, texture compression
How to invoke
Section titled “How to invoke”/t1k:cocos:playable:build-sizeCocos Playable Build Size Optimization
Section titled “Cocos Playable Build Size Optimization”Optimize Cocos Creator 3.8.7 playable ad builds for ad network size budgets (2–5 MB). Does NOT handle game logic (use t1k-cocos-playable-gameflow), parameters (use t1k-cocos-playable-parameter), or SDK integration (use t1k-cocos-playable-sdk-core).
Executed by
Section titled “Executed by”The read-only audit is aggregation-and-arithmetic against a fixed budget
table; applying any optimization is a judgment-gated file edit (routing SSOT:
rules/orchestration-rules.md § “Task-Type → Agent Routing”):
| Step | Agent |
|---|---|
Full Size Audit: read engine.json / builder.json / .meta settings, count assets, and tabulate current size vs the per-network budget table | t1k-metrics-reporter |
| Report findings with estimated savings per line item off the stated optimization tables (§ 1–7) | t1k-metrics-reporter |
Judge WHICH engine modules are actually safe to crop for this project’s gameplay (false-positive-heuristic risk, meshopt/meshCompress interaction) | stays on a reasoning tier — the tables state options, not which apply here |
Apply Optimizations workflow: any Edit/Write on engine.json, builder.json, or .fbx.meta/.gltf.meta/.glb.meta | stays on a write-capable, reasoning tier — mandatory Step 0 AskUserQuestion editor-closed gate, never cheap tier |
t1k-metrics-reporter has no Edit/Write tool, which matches the audit’s
own read-only shape — Step 0’s editor-closed confirmation and the readback
protocol are both destructive-blast-radius work per
rules/always-ask-on-unresolved.md § 6, and stay off it entirely.
Ad Network Size Limits
Section titled “Ad Network Size Limits”| Network | Max Size | Format |
|---|---|---|
| Meta/Facebook | 2 MB | Single HTML |
| Google Ads | 5 MB | Single HTML or ZIP |
| Unity Ads | 5 MB | Single HTML |
| IronSource | 5 MB | ZIP |
| AppLovin | 5 MB | Single HTML |
| TikTok | 2 MB | Single HTML |
| Voodoo | 5 MB | Single HTML |
| Mintegral | 5 MB | ZIP |
Size Optimization Checklist
Section titled “Size Optimization Checklist”1. Engine Module Pruning (Biggest Impact: 4–6 MB savings)
Section titled “1. Engine Module Pruning (Biggest Impact: 4–6 MB savings)”File: settings/v2/packages/engine.json
Minimal modules for a 2D playable ad:
"includeModules": [ "2d", "affine-transform", "animation", "audio", "base", "gfx-webgl", "graphics", "mask", "particle-2d", "rich-text", "tween", "ui"]Modules to REMOVE (with sizes): See references/engine-modules-guide.md
To modify: Open Cocos Editor → Project Settings → Feature Cropping. Or edit engine.json directly — update both cache (_value: false) and includeModules array.
2. Build Config Tuning
Section titled “2. Build Config Tuning”Files: ConfigPath/cfgTemplate.json, ConfigPath/cfgAndroidTemplate.json
| Setting | Optimal Value | Why |
|---|---|---|
experimentalEraseModules | true | Cocos’s JS dead-code removal. 10–30% engine JS reduction |
gfx-webgl2 (overwrite) | "off" | WebGL2 backend adds ~200 KB; most ad webviews use WebGL1 |
nativeCodeBundleMode | "wasm" | Smallest for web; "asmjs" fallback if WASM unsupported |
wasmCompressionMode | "gzip" or "brotli" | Compress remaining WASM (if any modules still need it) |
polyfills.asyncFunctions | false | Saves ~15 KB; modern webviews support ES2017 async/await |
bundleCommonChunk | false | Must be false for single-file HTML playable |
sourceMaps | false | No debug maps in production |
debug | false | Strips debug assertions |
Full settings reference: See references/build-config-reference.md
3. Texture Optimization
Section titled “3. Texture Optimization”File: settings/v2/packages/builder.json
| Setting | Optimal | Current Issue |
|---|---|---|
genMipmaps | false | Mipmaps add ~33% to texture data; useless for 2D |
| Compression quality | 70–80 | Quality 10 causes artifacts; 80 balances size/quality |
| WebP format | Add "webp": { "quality": 80 } | PNG-only misses 25–35% savings on web |
| Uncompressed textures | Apply preset to ALL | Check all .meta files have compressSettings |
Full texture & audio guide: See references/texture-audio-optimization.md
4. Audio Optimization
Section titled “4. Audio Optimization”Target: MP3/OGG, mono, 96 kbps for SFX, 128 kbps for BGM. Use optimize-size tool.
cd CocosPlayableAdsTemplate/tools/optimize-size && npm start# Opens http://localhost:3456 — browse and compress audio files5. Code-Level Optimizations
Section titled “5. Code-Level Optimizations”- 3D ParticleSystem imports force
3d+particlemodules. UseParticleSystem2Dinstead. import * as cc from "cc"pulls entire namespace — import specific classes.- Both SDK adapters always bundled via
SdkFactory. Minor issue, both are small. fs-extrain dependencies — should bedevDependencies(editor-only).
6. Asset Audit
Section titled “6. Asset Audit”- Remove unused assets from
game-assets/vfx/before shipping - Cocos only bundles scene-referenced assets, but accidental references happen
- Use
optimize-sizetool to identify large source assets
7. Model Compression (FBX / glTF) — Optional, only if shipping 3D
Section titled “7. Model Compression (FBX / glTF) — Optional, only if shipping 3D”If the playable contains 3D meshes (*.fbx, *.gltf, *.glb under game-assets/), per-asset .meta editing of meshCompress (quantize + meshopt encode) and meshSimplify (target-ratio decimation) typically drops mesh .bin files by 40–70%.
Critical interaction: meshCompress.encode: true REQUIRES the meshopt engine module to be enabled. If you previously cropped meshopt per § 1, you must re-enable it before turning encode on — otherwise runtime crashes with meshopt_decoder undefined.
Strategy split:
- Static meshes (field, props, ball) — full compress + simplify
targetRatio: 0.3–0.5 - Skinned meshes (character, hair, hands) — full compress but
meshSimplify.enable: false(ortargetRatio: 0.7+) to preserve skin weights
Full workflow including pre-change checklist, red-flag breakage table, rollback steps, and batch-script template: references/model-compression-guide.md
Workflow: Full Size Audit
Section titled “Workflow: Full Size Audit”Use direct file reads for engine and build configuration; no MCP tool exposes or mutates engine modules:
-
Check engine modules — Read/Grep
settings/v2/packages/engine.json; inspect bothcacheandincludeModules. -
Check build config — Read/Grep
settings/v2/packages/builder.jsonandConfigPath/*.json. -
Scan code for 3D imports — Grep with
ParticleSystem[^2]and inspect matching imports. -
Audit assets — Use direct file inspection for engine modules and build configuration; the Cocos MCP server has no settings-mutation or code-analysis tool:
-
Check engine modules — read
settings/v2/packages/engine.jsondirectly with Read/Grep. -
Check build config — read
settings/v2/packages/builder.jsonandConfigPath/*.jsondirectly with Read/Grep. -
Check texture configuration — inspect
builder.jsonand texture.metafiles directly.manage_project→get_settingsis read-only and does not expose engine modules. -
Scan code for 3D imports — use Grep with
ParticleSystem[^2]. -
Audit assets and dependencies — use
manage_asset→get_unusedandget_dependencieswhen MCP is connected. -
Check audio sizes — use the repository’s size-analysis tooling; there is no audio-stats MCP action.
-
Report findings with severity and estimated savings
Workflow: Apply Optimizations
Section titled “Workflow: Apply Optimizations”Step 0 — User Confirmation Gate (MANDATORY for direct file edits)
Section titled “Step 0 — User Confirmation Gate (MANDATORY for direct file edits)”Before any Edit / Write tool call on engine.json, builder.json, or any .fbx.meta / .gltf.meta / .glb.meta, you MUST invoke AskUserQuestion to confirm the Cocos Editor is fully closed. No exceptions. No “I already checked Task Manager” shortcuts — the user owns this confirmation. The editor watches these files and rewrites them from its in-memory state on its next save cycle, silently clobbering your edits. Blast radius is non-trivial: optimization work that appears committed but never ships.
Required gate sequence:
- Call
AskUserQuestionBEFORE the first direct edit with prompt:“I’m about to edit
<file>directly. Cocos Editor MUST be fully closed (verifyCocosCreator.exe/Creator.exeabsent in Task Manager) or my edits will be silently reverted on the editor’s next save cycle. Is the editor closed?” - Options:
[Editor closed — proceed],[Editor open — wait, I'll close it],[Cancel]. - Proceed ONLY on
closed — proceed. Onwait, pause and re-ask after the user signals closed. Oncancel, stop and report. - Optionally cross-check:
Get-Process CocosCreator -ErrorAction SilentlyContinue(PowerShell) ortasklist | findstr /i CocosCreator(cmd). If the process is detected after aclosed — proceedanswer, surface the mismatch to the user and re-ask — do NOT proceed silently. - The gate is required ONCE per workflow session for the same file set; if the user re-opens the editor mid-workflow you MUST re-gate before subsequent edits.
Exception — MCP path: there is no MCP path for engine-module or build-config mutations. The gate is always required before editing engine.json or builder.json; those edits require the Cocos Editor to be closed. Only texture compression via manage_asset → compress_textures may avoid this gate. Any direct file edit alongside MCP work ALWAYS triggers the gate.
Exception — non-watched files: ConfigPath/cfgTemplate.json and ConfigPath/cfgAndroidTemplate.json are Jenkins build templates outside settings/v2/packages/ and are not watched by the editor — Step 0 gate not required for these specific files.
Rule basis: rules/always-ask-on-unresolved.md § 6 — “Any deletion, overwrite, or destructive action whose blast radius is non-trivial — even if you have a strong default. Ask first.” Silent-revert qualifies as destructive blast radius.
Step 1 — Engine and build-config edits (editor closed)
Section titled “Step 1 — Engine and build-config edits (editor closed)”Step 0 User Confirmation Gate is mandatory for this entire path. There is no MCP settings-mutation tool; engine and builder configuration are always edited as files with the editor closed.
- Quit Cocos Editor fully (verify in Task Manager —
CocosCreator.exeabsent). - Edit
engine.json— flip_value: falseAND remove fromincludeModulesfor each cropped module. - Edit
builder.jsonandcfgTemplate.json/cfgAndroidTemplate.jsonas needed. - User reopens editor → declines any “re-enable module X” prompt unless grep confirms actual usage (see reference grep table).
- Mandatory readback — re-read
engine.jsonafter reopen; confirm every cropped module is still_value: falseAND absent fromincludeModules. Report drift explicitly. Never claim “done” before this step. - Fix code — replace 3D
ParticleSystemwithParticleSystem2Dif appropriate, then rebuild and verify output size.
Step 2 — MCP texture compression (optional)
Section titled “Step 2 — MCP texture compression (optional)”If Cocos MCP Server is connected, manage_asset → compress_textures may run while the editor is open. Use supported quality/format parameters; do not use MCP for engine or builder settings.
Common Mistakes
Section titled “Common Mistakes”- Editing
engine.jsonwhile Cocos Editor is open — editor reverts the file from its in-memory state. ALWAYS run the Step 0 User Confirmation Gate (Workflow: Apply Optimizations) before any direct edit. Never skip on the basis of “I already checked Task Manager” — the user owns the confirmation. - Editing
engine.jsonbut forgetting to update bothcache._valueandincludeModules— must update BOTH - Editing the wrong config block — multiple configs can exist (
migrationsConfig,custom-config-{uuid}); only the one named inmodules.globalConfigKeyis active. - Reporting “modules cropped” without re-reading the file after the user reopens the editor — the editor’s auto-scan may have reverted some via false-positive heuristics.
- Trusting prior session’s “this module is already off” claims — always read the actual
_valueandincludeModulesarray; never assume. - Setting texture quality too low (10) — causes visible artifacts, especially on VFX
- Keeping
profilermodule enabled — adds FPS overlay code to production builds - Forgetting
genMipmaps: false— 33% texture waste, invisible in dev but bloats build - Using
"gfx-webgl2": "on"when targeting ad webviews that don’t support WebGL2 - Not applying texture compression preset to all textures (check each
.metafile) - Enabling
meshCompress.encode: truewhile themeshoptengine module is cropped — runtimemeshopt_decoder undefinedcrash. Always re-enablemeshoptfirst. - Running
meshSimplifyon skinned character meshes with defaulttargetRatio: 0.4— collapses vertices that share skin weights, producing distorted limbs. Disable simplify on skinned meshes or raise ratio to0.7+. - Editing
.fbx.metawhile Cocos Editor is open — same trap asengine.json. Editor re-imports and reverts your changes. Step 0 User Confirmation Gate applies to.fbx.meta/.gltf.meta/.glb.metaedits too. - Deleting a
.fbx.metato “start fresh” instead of editing in place — invalidates the UUID and orphans every prefab reference. Always edit, never recreate.
Gotchas
Section titled “Gotchas”- Cocos MCP has no settings-mutation tool. Feature cropping is file-edit-only; verify with
grep -rho "name: *'manage_[a-z_]*'" --include="*.ts" ./source | sort -u(20 tools). - Cocos Editor silently reverts
engine.json/builder.json/*.fbx.metaedits while open. Step 0 User Confirmation Gate (Workflow: Apply Optimizations) is MANDATORY before any directEdit/Writetool call on these files — callAskUserQuestionto make the user confirm editor is closed. AI-side process checks (Get-Process/tasklist) supplement but do NOT replace the user confirmation. Details + active-config rule + post-edit readback protocol + false-positive grep table:references/engine-modules-guide.md§ Editor Workflow Pitfalls. - Feature cropping has no editor-visible effect. Scene/preview always renders with the full engine. Savings only appear in final BUILD output — verify via
tools/optimize-sizeor build folder size diff, never editor view. - Build size cap for ad networks: typically 5MB — going over silently fails on AdMob, hard-rejects on Meta.
- Inlining base64 assets blows up minified JS — keep large assets as separate URLs and gate
crossOrigin: 'anonymous'. - TerserPlugin defaults preserve class names; flip
mangle: { keep_classnames: false }for an extra ~5% reduction. - Model compression has a hard dependency on the
meshoptengine module. Croppingmeshoptis the right call for 2D-only playables, but the moment any.fbx.metahasmeshCompress.encode: truethe module becomes mandatory. Cross-check before flipping either side. Full workflow:references/model-compression-guide.md. .fbx.metaUUID is referenced by every prefab that uses the model. Never delete-and-recreate a.meta— always edit in place. Restoring from.meta.bakis safe; regenerating from scratch is not.- Cocos has no project-wide model compression preset. Each
.fbx.metais configured individually. For projects with 20+ models, batch via a Node.js script (template in the reference) with the editor closed.
Step 1 — Apply with MCP Server where supported
Section titled “Step 1 — Apply with MCP Server where supported”Engine-module and build-config changes still follow Step 0: close the Cocos Editor, then edit engine.json / builder.json directly. If MCP is connected, the only editor-aware optimization mutation is manage_asset → compress_textures with supported quality and format parameters. Then edit config/code as needed, rebuild, and verify output size.
super-html Packer Gotchas
Section titled “super-html Packer Gotchas”super-html is a single-file HTML packer some projects run as an onAfterBuild hook on the web-mobile build target, to produce the single-file HTML most ad networks require (see the network table above). Measured 2026-09-03 with super-html 5.4.0 on Cocos Creator 3.8.7 — four gotchas that fail silently or hang, plus one unrelated build-freshness trap that surfaces at the same point in the pipeline:
- It refuses builds containing
.wasm. Build withnativeCodeBundleMode: "asmjs"instead of the"wasm"value § 2 recommends for size — the size/format tradeoff inverts when super-html is the packer. CLI:CocosCreator.exe --project <p> --build "platform=web-mobile;debug=false;nativeCodeBundleMode=asmjs". The Cocos MCP’smanage_project→buildaction only opens the build panel in the editor; it does not run a headless build, so it cannot be used to drive this pipeline. - It STRIPS every inline
<script>from the builtindex.htmland rebuilds the page from its own template. Abuild-templates/web-mobile/index.htmlsnippet (a gtag/SDK shim, for example) never reaches the packed output — HTML comments survive the rebuild,<script>tags do not. Anything that must execute in the packed page has to live in bundled TypeScript instead, not the HTML template. - A remote
<script src="https://...">in the template crashes the packer withENOENT .../build/web-mobile/https:/...— it treats everysrcas a local file path with no scheme check. The CLI build then hangs with no “Finished” line printed, so a CI job waiting on that line times out rather than failing fast. - It regex-rewrites
X.createElement("script")literals into a_createLocalJSElement()stub — an inert<_my>element that silently ignores a remotesrc. Aliasing the literal (const SCRIPT_TAG = "script") is not enough to dodge the regex: the Cocos release minifier inlines the constant back into the literal before super-html ever sees the file. The workaround that survives minification isdocument.createElement.call(document, SCRIPT_TAG)— verified surviving intact in the packed bundle. - Related build-freshness trap, same symptom class: starting a CLI build within roughly 1–2 minutes of writing a
.tsfile underassets/while the editor is still open can snapshot a mid-recompile script graph — a handful of modules instead of the project’s full set (~700 in a typical playable). The result is aMissing class: <cid>error for every component and a packed HTML that dies at scene load with engine error 16352 (Cannot read properties of null (reading '__prefab')). Before trusting a build, confirmgrep -c "Missing class" temp/builder/log/web-mobile*.logreturns0.