大家好,想分享一下 Cocos Creator 4 的 Worker 和 WorkerPool 用法。这里用一个实际任务来对比: 游戏运行时要给大网格减面,能不能一边算,一边让画面继续流畅更新?
Demo 使用一份 32.8 万三角形 的地形网格。相机每 6 秒往返一轮,按距离切换 LOD0–5。LOD0 使用原网格,每次进入较低等级时重新计算简化索引,方便反复观察切换时的卡顿。主线程和 Worker 路径使用同一套 Meshopt WASM 算法。无论在哪算,结果校验、创建 Mesh 和更新 LODGroup 都在主线程。
三种模式的区别,在于计算放在哪里,以及谁管理任务。
| 模式 | 运行方式 | 适用场景 |
|---|---|---|
| 主线程 | 直接调用减面函数,等结果出来再继续 | 建立对照基线;任务很轻时也省去通信成本 |
| 直接 Worker | 用 createWorker() 启动脚本,自己处理消息、超时和销毁 |
已有自己的任务协议,或希望长期复用一个 Worker |
| WorkerPool | 用 pool.run() 提交任务,由引擎处理排队、并发和超时 |
需要持续提交多项独立任务,想复用引擎的调度 |
LOD Demo 的池固定使用 1 个 Worker 。这组对比看的是把一项重计算移出主线程之后,画面能否继续更新。增加池大小也不会自动把一次减面拆成多份。
开启功能后,可以先用球体场景跑通三种模式,再看 LOD 的帧间隔。
- 使用包含
worker和worker-pool功能的 4.0 引擎,例如引擎源码4.0.0-beta.1。如果编辑器里找不到对应选项,先检查项目实际加载的引擎。 - 打开 项目 → 项目设置 → 功能裁剪 → Worker 。只用
createWorker(),开启 基础 Worker 功能 ;需要WorkerPool,再开启 Worker Pool ,它会联动开启基础项。两个接口都从cc导入。官方使用手册 - 打开官方测试项目
v4.0.0分支的assets/cases/scene/worker-test/worker.scene。场景按钮可以切换 单线程 / 自动 Worker ;在组件的 Worker 管理方式 里选择 直接 Worker / WorkerPool 。把这两个选项组合起来,就能体验三种方式。控制台筛选[worker-test],看实际后端和计算校验结果。 - 性能对比用
worker-lod.scene( Demo 下载链接待补 )。打开后等待[WorkerLOD] ready,滑条保持在中间的自动档。勾选框或 Web 快捷键M可以切换主线程和 WorkerPool,从下一次减面任务生效。每档跑几个相机往返周期再比较。
如果想把 同一个 LOD 任务 改为直接 Worker,脚本也可以复用:用 createWorker() 加载同一个 simplify-worker.js ,发送 { id, args: [input] } ,按 id 匹配返回的结果或错误,再交给原有的校验和建 Mesh 流程。对比时保持相同输入、LOD 比例和消息传输方式,并在多次任务之间复用 Worker,避免把每次创建线程的成本算进其中一档。
验证时,先看任务在哪执行,再看结果和帧间隔。
-
实际后端 :确认任务成功,且日志显示
backend=worker。sync表示同步执行;拿到 Promise 或看到界面勾选了 Worker,都不能证明任务跑在后台。 -
结果一致性 :对比相同 LOD 的输出三角数和
resultHash,避免把不同减面等级混在一起。Hash 适合快速核对,正式验证可以逐项比较索引。 -
性能 :在
[WorkerLOD] result里看maxFrameMs、totalMs和applyMeshMs。最大帧间隔反映切换期间有没有明显卡顿;任务总耗时还包含通信和回填。首次启动和热身后的样本分开看。
之前在 Apple M5 / macOS、本地 Web Mobile 调试构建 的短测中,主线程档的任务期间最大帧间隔约 58–95 ms ,WorkerPool 档约 21–23 ms 。这个结果说明该场景里,后台减面缓解了主线程长帧。 它不是通用加速比,也没有包含直接 Worker 的同负载数据。
平台上有几个使用条件:
| 平台 | 使用条件 |
|---|---|
| Web | LOD 示例用独立脚本,构建后确认 Worker JS 能通过 HTTP(S) 访问,并满足同源和 CSP 要求。这个示例还要求 Worker 环境能初始化 Meshopt WASM。 |
| 微信小游戏 | 使用打包后的独立 JS,确认脚本在 game.json 声明的 workers 目录下。V1/V2 使用同一个创建入口,由运行时识别;V1 可使用一个 Worker,但不支持 transfer。LOD 示例在微信侧还依赖 Worker 能加载包内 WASM,目前只验证过构建, 没有微信真机性能结论 。 |
| Native | 当前这套接口不启动 JS Worker。业务可以提供主线程实现;WorkerPool 脚本模式配置 fallback 后,才有同步回退路径。LOD 性能用例会明确报出 Worker 不可用,避免把回退当作 Worker 成功。 |
比较推荐从 输入输出明确、计算开销较大 的任务开始试,例如网格处理、寻路批次、数据解析。这个 Demo 迁出去的是减面计算,场景更新和渲染仍按原来的流程执行。
最后可以看看这个视频的效果:
worker-lod2.mov.zip (2.7 MB)
