Skip to content

t1k:cocos:playable:build-size

FieldValue
Moduleplayable
Version2.14.4
Efforthigh
Tools—

Keywords: build size, engine module, FBX, glTF, mesh compress, meshopt, model compression, optimization, texture compression

/t1k:cocos:playable:build-size

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).

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”):

StepAgent
Full Size Audit: read engine.json / builder.json / .meta settings, count assets, and tabulate current size vs the per-network budget tablet1k-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.metastays 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.

NetworkMax SizeFormat
Meta/Facebook2 MBSingle HTML
Google Ads5 MBSingle HTML or ZIP
Unity Ads5 MBSingle HTML
IronSource5 MBZIP
AppLovin5 MBSingle HTML
TikTok2 MBSingle HTML
Voodoo5 MBSingle HTML
Mintegral5 MBZIP

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.

Files: ConfigPath/cfgTemplate.json, ConfigPath/cfgAndroidTemplate.json

SettingOptimal ValueWhy
experimentalEraseModulestrueCocos’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.asyncFunctionsfalseSaves ~15 KB; modern webviews support ES2017 async/await
bundleCommonChunkfalseMust be false for single-file HTML playable
sourceMapsfalseNo debug maps in production
debugfalseStrips debug assertions

Full settings reference: See references/build-config-reference.md

File: settings/v2/packages/builder.json

SettingOptimalCurrent Issue
genMipmapsfalseMipmaps add ~33% to texture data; useless for 2D
Compression quality70–80Quality 10 causes artifacts; 80 balances size/quality
WebP formatAdd "webp": { "quality": 80 }PNG-only misses 25–35% savings on web
Uncompressed texturesApply preset to ALLCheck all .meta files have compressSettings

Full texture & audio guide: See references/texture-audio-optimization.md

Target: MP3/OGG, mono, 96 kbps for SFX, 128 kbps for BGM. Use optimize-size tool.

Terminal window
cd CocosPlayableAdsTemplate/tools/optimize-size && npm start
# Opens http://localhost:3456 — browse and compress audio files
  • 3D ParticleSystem imports force 3d + particle modules. Use ParticleSystem2D instead.
  • import * as cc from "cc" pulls entire namespace — import specific classes.
  • Both SDK adapters always bundled via SdkFactory. Minor issue, both are small.
  • fs-extra in dependencies — should be devDependencies (editor-only).
  • Remove unused assets from game-assets/vfx/ before shipping
  • Cocos only bundles scene-referenced assets, but accidental references happen
  • Use optimize-size tool 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 (or targetRatio: 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

Use direct file reads for engine and build configuration; no MCP tool exposes or mutates engine modules:

  1. Check engine modules — Read/Grep settings/v2/packages/engine.json; inspect both cache and includeModules.

  2. Check build config — Read/Grep settings/v2/packages/builder.json and ConfigPath/*.json.

  3. Scan code for 3D imports — Grep with ParticleSystem[^2] and inspect matching imports.

  4. Audit assets — Use direct file inspection for engine modules and build configuration; the Cocos MCP server has no settings-mutation or code-analysis tool:

  5. Check engine modules — read settings/v2/packages/engine.json directly with Read/Grep.

  6. Check build config — read settings/v2/packages/builder.json and ConfigPath/*.json directly with Read/Grep.

  7. Check texture configuration — inspect builder.json and texture .meta files directly. manage_project → get_settings is read-only and does not expose engine modules.

  8. Scan code for 3D imports — use Grep with ParticleSystem[^2].

  9. Audit assets and dependencies — use manage_asset → get_unused and get_dependencies when MCP is connected.

  10. Check audio sizes — use the repository’s size-analysis tooling; there is no audio-stats MCP action.

  11. Report findings with severity and estimated savings

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:

  1. Call AskUserQuestion BEFORE the first direct edit with prompt:

    “I’m about to edit <file> directly. Cocos Editor MUST be fully closed (verify CocosCreator.exe / Creator.exe absent in Task Manager) or my edits will be silently reverted on the editor’s next save cycle. Is the editor closed?”

  2. Options: [Editor closed — proceed], [Editor open — wait, I'll close it], [Cancel].
  3. Proceed ONLY on closed — proceed. On wait, pause and re-ask after the user signals closed. On cancel, stop and report.
  4. Optionally cross-check: Get-Process CocosCreator -ErrorAction SilentlyContinue (PowerShell) or tasklist | findstr /i CocosCreator (cmd). If the process is detected after a closed — proceed answer, surface the mismatch to the user and re-ask — do NOT proceed silently.
  5. 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.

  1. Quit Cocos Editor fully (verify in Task Manager — CocosCreator.exe absent).
  2. Edit engine.json — flip _value: false AND remove from includeModules for each cropped module.
  3. Edit builder.json and cfgTemplate.json / cfgAndroidTemplate.json as needed.
  4. User reopens editor → declines any “re-enable module X” prompt unless grep confirms actual usage (see reference grep table).
  5. Mandatory readback — re-read engine.json after reopen; confirm every cropped module is still _value: false AND absent from includeModules. Report drift explicitly. Never claim “done” before this step.
  6. Fix code — replace 3D ParticleSystem with ParticleSystem2D if 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.

  • Editing engine.json while 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.json but forgetting to update both cache._value and includeModules — must update BOTH
  • Editing the wrong config block — multiple configs can exist (migrationsConfig, custom-config-{uuid}); only the one named in modules.globalConfigKey is 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 _value and includeModules array; never assume.
  • Setting texture quality too low (10) — causes visible artifacts, especially on VFX
  • Keeping profiler module 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 .meta file)
  • Enabling meshCompress.encode: true while the meshopt engine module is cropped — runtime meshopt_decoder undefined crash. Always re-enable meshopt first.
  • Running meshSimplify on skinned character meshes with default targetRatio: 0.4 — collapses vertices that share skin weights, producing distorted limbs. Disable simplify on skinned meshes or raise ratio to 0.7+.
  • Editing .fbx.meta while Cocos Editor is open — same trap as engine.json. Editor re-imports and reverts your changes. Step 0 User Confirmation Gate applies to .fbx.meta / .gltf.meta / .glb.meta edits too.
  • Deleting a .fbx.meta to “start fresh” instead of editing in place — invalidates the UUID and orphans every prefab reference. Always edit, never recreate.
  • 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.meta edits while open. Step 0 User Confirmation Gate (Workflow: Apply Optimizations) is MANDATORY before any direct Edit / Write tool call on these files — call AskUserQuestion to 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-size or 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 meshopt engine module. Cropping meshopt is the right call for 2D-only playables, but the moment any .fbx.meta has meshCompress.encode: true the module becomes mandatory. Cross-check before flipping either side. Full workflow: references/model-compression-guide.md.
  • .fbx.meta UUID is referenced by every prefab that uses the model. Never delete-and-recreate a .meta — always edit in place. Restoring from .meta.bak is safe; regenerating from scratch is not.
  • Cocos has no project-wide model compression preset. Each .fbx.meta is 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 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 with nativeCodeBundleMode: "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’s manage_project → build action 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 built index.html and rebuilds the page from its own template. A build-templates/web-mobile/index.html snippet (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 with ENOENT .../build/web-mobile/https:/... — it treats every src as 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 remote src. 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 is document.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 .ts file under assets/ 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 a Missing 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, confirm grep -c "Missing class" temp/builder/log/web-mobile*.log returns 0.