ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

CocosCreator 游戏包体超过 4M?从资源压缩到分包加载的实战优化指南

CocosCreator 游戏包体超过 4M?从资源压缩到分包加载的实战优化指南 1. 为什么你的 CocosCreator 游戏会莫名其妙“膨胀”到 4M 以上做 CocosCreator 开发的朋友应该都有过这种经历辛辛苦苦把玩法调通想着打包发布应该没啥问题了结果一看构建产物——好家伙包体直接奔着 5M、6M 甚至更高去了。在微信小游戏这类平台4M 是一个挺敏感的数字超过之后加载速度和审核体验都会打折扣有些渠道甚至会对包体大小有硬性限制。所以“CocosCreator 2.x/3.x 游戏体积超过 4M 怎么办”这个问题几乎是每个小游戏开发者绕不过去的坎。先说一个反直觉的结论很多时候包体膨胀的根本原因不是你的代码写得多而是资源管理太粗放。我以前带过的一个项目玩法逻辑加起来不到 1M但整包愣是做到了 7.8M。后来一查光 UI 图集就有 3 个是重复打包的还有一堆从来没被引用到的预制体资源躺在 assets 里“吃灰”音频文件直接丢的 wav 格式一个 3 分钟的背景音乐就占了 20 多 M 的原始素材——虽然构建时会压缩但压缩后的体积依然可观。这篇文章不去讲那些“官方文档里都有”的泛泛而谈而是围绕我在 2.x 和 3.x 两个版本上都踩过的坑聊一些真正能落地、能立刻把包体压下来的手段。无论你是刚接触 CocosCreator 的新手还是已经发布了几个小游戏的老手只要你正在为包体发愁这篇文章应该能给你一些可操作的思路。啥叫“可操作”就是你看完这篇文章打开你的项目照着下面这些步骤去检查、去调整大概率能在半小时内发现至少两三个可以优化的点。如果一个优化点能帮你省下几百 KB那整体包体从 6M 降到 4M 以下并不是什么难事。2. 先搞清楚 4M 这个门槛到底卡在哪儿在动手优化之前我们得先弄清楚一个问题这 4M 到底是指什么不同时期、不同平台的规则其实不太一样理解错了容易白费功夫。2.1 主包 4M 与分包 20M 的边界逻辑以微信小游戏为例早年间是主包不能超过 4M后来调整成主包 4M、总包 20M 的机制。也就是说你可以在主包之外加载分包资源但主包本身依然有 4M 的限制。很多开发者的误区在于拼命压缩主包内的所有东西却忽略了分包的存在。其实有些内容是可以合理拆到分包里去的比如不常访问的游戏关卡、只在特定界面出现的资源、后期运营活动资源等。把这些东西拆出去之后主包的压力会小很多。在 CocosCreator 2.x 里你可以在构建发布面板中配置“分包设置”把 Bundle 名填进去资源就会按 Bundle 维度拆开。3.x 版本的操作方式略有不同但思路一致通过配置 Bundle 和构建发布时的分包选项来实现。2.2 你真正需要关心的首包加载 vs 总包体积还有个概念要分清楚首包大小和总包大小。首包是玩家第一次进入游戏时需要加载的内容总包则包含了后续可能用到的所有内容。有些团队为了追求总包体积小于某个值把大量首包必要的 UI 资源也压缩得面目全非结果画面质量严重下降玩家体验变差。实际上如果只是首包超过 4M而总包能控制在合理范围你完全可以通过“合理拆包 加载优化”来解决而不必一味压缩资源质量。我的建议是先画一张资源依赖图把“首屏必须展示的界面/场景”和“后续才需要的内容”区分开。首屏只放必要资源其余一律想办法延迟加载或分包加载。这一步想清楚了后面的优化才有方向否则你就是瞎忙活。3. CocosCreator 2.x 下的包体压缩实操我在 2.x 上做优化相对多一些也踩过不少坑先说这个版本里最有效的几个优化手段。3.1 图片资源压缩不只是改个格式那么简单图片往往是包体膨胀的第一大元凶。很多美术同学给资源的时候喜欢直接丢原图一张 2048×2048 的 PNG 就可能 5M-10M这对小游戏来说完全是灾难。在 CocosCreator 2.x 里图片资源有两个关键属性Type和Format。在资源管理器中选中图片在属性检查器里能看到。Type 通常设置为 sprite-frameFormat 则可以选择压缩格式。实战中最常用的组合UI 界面图片使用 JPG 格式质量 80% 左右代替 PNG如果是纯色或渐变色 UI肉眼几乎看不出差别带透明通道的图片使用 PNG 压缩或者在构建时开启 PNG 压缩算法大尺寸背景图适当降低图片尺寸从 1920×1080 降到 1600×900画质损失有限但体积急剧下降这里有一个很多新手不知道的点CocosCreator 2.x 构建时如果你开启了“压缩纹理”选项那么构建产物里的图片会统一走 texture compression 流程。但默认情况下这个选项不一定开你得去构建发布面板里手动勾选。提示勾选压缩纹理之后首次构建时间会明显变长因为引擎需要对所有图片进行重压缩处理。这是正常的别以为是卡死了。但压缩纹理有兼容性问题尤其是低端 Android 机型上某些压缩格式如 ETC1不支持透明通道处理不好会出现图片发黑、花屏等问题。我的经验是iOS 平台使用 ASTC 压缩格式效果最佳Android 平台根据目标规格使用 ETC2 或 ASTC4×4 或 6×6 的 block 尺寸都需要测试Web 平台通常用原图 PNG/JPG配合 HTTP 压缩就够用3.2 图集合批减少 DrawCall 的同时不给包体增负图集不只影响渲染性能也直接影响包体体积。CocosCreator 2.x 提供了自动图集功能在资源管理器的assets目录下右键 → 新建 → 自动图集配置生成一个.pac文件。创建好自动图集配置后把需要合批的图片拖进去构建时就会自动打包成一张大图。这样做的好处有两点减少 DrawCall提升渲染性能去除图片之间的空隙和冗余信息整体体积反而比单张图片总和要小但要注意自动图集配置的格式设置同样要遵循前面讲的压缩纹理规则。很多时候我把图片都塞进了图集但图集本身的压缩格式没设置对包体照样大得离谱。实际操作中我一般会建多个自动图集按场景或模块划分UI-Common所有通用 UI 元素UI-Home主界面相关UI-Battle战斗界面相关Map-Tiles地图瓦片素材这样做也让后续的资源维护更清晰——想给某个模块加图片直接拖进对应图集即可不用去翻找散落各处的图片文件。3.3 音频资源的格式选择别迷信 MP3音频在包体中的占比经常被忽视。我的经验是CocosCreator 2.x 对音频格式的兼容性其实没有想象中那么好MP3 并不是所有机型都支持。推荐的做法背景音乐BGM使用压缩率高的格式如.m4a或压缩后的.mp3采样率 44.1kHz 降到 32kHz立体声转单声道体积可以砍掉 60% 以上音效SFX使用短音频 wav 转 ogg 或 m4a保留原始音色但大幅压缩体积在导入音频资源后记得在属性检查器中把加载类型设置为NONE不预加载或者ON_DEMAND按需加载。默认的INTERNAL会导致音频在游戏启动时就被加载到内存中如果音频多内存和启动速度都会受影响。3.4 代码层面的瘦身从源头上减少重复逻辑代码文件占的体积通常不大但如果不注意几个小问题加起来也能产生数 MB 的额外包体。第一种情况是重复导入相同的库。比如说你为了某个小功能引入了一个第三方库而另一个库内部其实也内置了这个功能结果就是同一份代码被打包了两遍。这种情况在 CocosCreator 2.x 的插件生态里很常见。第二种情况是过度使用动态加载但静态引用。举个典型场景你在代码里写resources.load(xxx/prefab)但同时又把这个 prefab 放进了 Bundle 的静态引用列表中构建时它就被打进了主包。你以为它是动态加载的其实它早就住在主包里了。排查方法很简单在构建后的build/jsb-link或build/wechatgame目录下搜索资源名称看看它出现在哪些 Bundle 目录里。如果出现在主包目录而你的代码里明明写着动态加载那就是引用关系出了问题。注意在 CocosCreator 2.4 里resources目录下的所有资源默认会打进resources这个 Bundle。你如果用了resources.load那这些资源就已经在主包里了除非你把它移到非 resources 目录下的自定义 Bundle 里。4. CocosCreator 2.x 常见误区与避坑记录优化做多了碰到的坑自然也多了。这里挑几个最有代表性的误区希望能帮你少走弯路。4.1 “删了资源怎么包体没变小”这是最经典的问题。我有个项目美术删掉了三百多 MB 的原始素材结果构建出来的包体几乎没变化。原因很简单CocosCreator 的构建过程会自动清除未被引用的资源而美术删掉的那批素材本来就没被任何场景、预制体、代码引用到它们根本不会进入包体。也就是说你在 asset 目录下看到的所有资源并不等于最终包体里的内容。构建时引擎会做资源依赖分析只有被引用到的资源才会被包含进来。那什么情况下删除资源会影响包体体积这个资源被某个场景、预制体、动画等文件引用了删除后引用断掉包体缩小这个资源被代码通过resources.load或其他路径字符串引用了删除后代码报错或加载失败但包体会缩小这个资源被设置为 Bundle 的“主资源”或“静态资源”删除后 Bundle 中的内容减少所以别只顾着删素材要检查的是“引用关系图”。4.2 压缩纹理开得越猛越好未必我曾经在一个 Android 项目上把压缩纹理全部设置为 ETC1包体确实小了很多但运行的时候出现了一个诡异的问题部分 UI 图片变成了黑块。查了半天最终发现问题出在 ETC1 不支持透明通道。UI 图片带透明通道的非常多一旦压缩格式选错就会花屏。正确的做法是把透明图和非透明图分开处理。透明图UI 图标、特效帧等用 ETC2 或 ASTC非透明图背景图、照片类图片用 ETC1 或 ASTC。CocosCreator 2.x 的自动图集支持设置不同的压缩格式所以你需要维护多套图集来区分。4.3 “图片瘦身了但构建后的包体还是很大”这种情况通常是因为还有大量的 JSON 或动画文件未被关注。CocosCreator 的动画文件.anim、预制体.prefab、场景.scene本质上都是 JSON 格式如果资源数量庞大这些文件的体积积累起来也很可观。对策删除不再使用的动画剪辑和预制体合理拆分场景避免一个超大场景包含所有内容尽量使用代码驱动 UI 动态创建而不是放置大量预制体在场景中5. CocosCreator 3.x 下的包体优化思路升级到了 3.x引擎架构做了比较大的调整资源管理方式、构建流程和 2.x 有明显差异包体优化的手段也需要跟着调整。5.1 Asset Bundle 在 3.x 中的新玩法3.x 里 Asset Bundle 依然存在但配置方式更灵活了。你可以在项目设置里直接配置 Bundle也可以右键资源目录 → 创建 Bundle 配置。不过 3.x 有一个和 2.x 不同的点3.x 默认把资源按“所属 Bundle”进行划分而且允许你更精确地控制哪些资源是 Bundle 的“启动资源”。这意味着你可以控制玩家进入某个子包时才加载的启动资源而不像 2.x 那样要么全部进包要么全部不进。实际操作时我会把每个玩法模块做成独立的 Bundle并设置一个“启动场景”或“启动依赖”。当玩家进入对应玩法时再调用bundle.load加载对应资源。// CocosCreator 3.x 动态加载自定义 Bundle 资源示例 assetManager.loadBundle(game-level-1, (err, bundle) { if (err) { console.error(Bundle 加载失败: , err); return; } bundle.load(prefabs/EnemySpawner, Prefab, (err, prefab) { if (err) { console.error(Prefab 加载失败: , err); return; } // 实例化预制体到场景中 const node instantiate(prefab); director.getScene().getChildByName(Canvas).addChild(node); }); });这种按模块拆包的思路能让首包大小大幅降低。我做过一个项目所有玩法逻辑都塞在主包里时首包 6.5M改成按关拆分 Bundle 后首包降到 3.2M加载速度肉眼可见地提升了。5.2 3.x 的压缩纹理配置粒度更细坑也更细3.x 在压缩纹理方面提供了更细的控制粒度你可以针对不同类型的资源设置不同的压缩参数。但随之而来的是配置项的复杂度提升。我的建议在 3.x 里统一使用 ASTC 6×6 作为默认压缩格式在高端机型上可以适当使用更高配比的 ASTC 4×4画质更好低端机则可以用 ASTC 8×8体积更小。如果项目需要兼容特别老的机型再考虑 ETC2。注意:3.x 里如果使用 ASTC 但在某些不支持 ASTC 的机型上运行纹理加载会回退到软件解码导致内存暴涨。所以如果要兼容老机型最好能有一个运行时检测并根据检测结果动态加载不同格式的纹理资源。这个流程稍复杂但做一次之后适配问题能省心很多。5.3 代码分包与远程资源3.x 项目的终极优化手段如果包体实在压不下来可以通过代码分包再挤一挤。3.x 支持把一部分代码做成子包在构建时生成独立文件然后按需加载。常见的模式主包引擎核心 启动场景 基础 UI子包1玩法核心逻辑代码子包2数值、剧情文本、关卡配置子包3后期运营活动资源说实话远程资源的方案在小游戏平台上有一些限制需要域名白名单、需要 HTTPS但在某些支持度更高的平台上比如原生打包效果非常明显。之前我接的一个原生包需求把 60% 的资源放到 CDN 上只留核心引擎和 UI 在主包最终首包只有 2M 多一点。5.4 3.x 的远程资源加载陷阱远程资源加载有一个容易踩的坑远程资源无法享受引擎的内存自动管理。如果你频繁加载远程资源、销毁节点后又重新加载内存会越积越多最终导致低端机卡死或闪退。解决方式是在销毁节点后显式调用assetManager.releaseAsset或resources.release释放远程加载的资源。// 远程加载完成后在合适的时候释放资源 assetManager.loadRemote(https://example.com/textures/level-bg.png, (err, texture) { if (err) return; // 使用纹理... // 某个时机释放该纹理 assetManager.releaseAsset(texture); });这个陷阱在 2.x 中也存在但在 3.x 中因为是推荐做法大家用得多了踩坑的频率也随之上升。6. 必须掌握的包体分析工具让优化有的放矢手动排查资源问题虽然可靠但当项目规模变大之后会非常耗时。借助工具才能高效定位问题。6.1 Cocos Creator 构建产物目录结构解读每次构建完成后在build目录下会生成对应平台的构建产物。以微信小游戏为例构建后你会在build/wechatgame目录下看到assets文件夹 —— 资源文件包含纹理、音频、JSON 等src文件夹 —— 项目代码和引擎代码project.config.json—— 微信开发者工具的配置game.json—— 小游戏入口配置在assets文件夹下你可以看到按 Bundle 区分的子目录。比如main表示主包资源resources表示resourcesBundle 的资源自定义 Bundle 名如game-level-1则对应拆出去的子包资源。看这些目录下的文件大小你能快速知道每个 Bundle 占了多少体积进而判断哪些资源可以进一步压缩或拆包。6.2 用构建日志定位体积异常的元凶CocosCreator 构建时会在控制台输出日志其中包含每个 Bundle 的打包详细信息。你可以在构建完成后查看输出找到Build Bundle: xxx之类的日志。如果嫌日志太多也可以直接对比构建产物目录中各文件的大小。我一般会用系统自带的文件管理器按体积排序从大到小排查。如果某个文件体积特别大但又不属于图片或音频那有可能是某种资源被打包格式不合理导致的需要回到编辑器里检查对应资源的类型设置。6.3 第三方工具辅助分析可选如果你使用微信小游戏作为发布平台微信开发者工具自带的“代码依赖分析”功能也能辅助定位主包中到底有哪些资源。不过这个功能的提示有时候不够人性化需要结合 CocosCreator 的构建产物一起看才能定位准确。另外一个思路是在 CocosCreator 编辑器里点击“资源管理器”的“项目”视图右键选择“在资源管理器中显示”把项目资源按大小排序看看哪些资源文件体积排名靠前。这些“大块头”往往就是需要重点优化的对象。7. 完整案例拆解6.8M 到 3.9M 的优化全过程理论讲得再多不如来一个真实的案例拆解。这个项目是我之前接手的一个休闲类小游戏包体 6.8M目标是压到 4M 以内。整个过程大概花了一个下午动手前先花半小时做了分析。7.1 第一步资源盘点找到体积大王我用文件管理器对构建产物按大小排序优先关注前几名的文件。结果发现排名第一的是一张 2048×2048 的 UI 背景图PNG 格式构建后竟然还有 1.7M排名第二的是两段背景音乐MP3 格式各占 700K-900K第三是一整套逐帧动画序列帧16 张 512×512 的 PNG构建后合计近 1M这三项加起来就 3.6M 左右难怪包体这么大。7.2 第二步资源替换与压缩针对发现的问题我逐个处理背景图从 PNG 改为 JPG质量 85%尺寸从 2048×2048 降到 1400×1400体积从 1.7M 降到 250K背景音乐转码为 m4a 格式采样率从 44.1kHz 降到 32kHz立体声转单声道体积从 700K 降到 150K 左右逐帧动画将 16 张序列帧合入一个自动图集开启压缩纹理ASTC 6×6体积从 1M 降到 300K这一波操作直接砍掉了约 2.5M。7.3 第三步代码与依赖清理检查了代码引用后发现有几个预制体被resources.load和静态引用同时使用导致它们在主包里重复出现。清理掉静态引用、统一走动态加载后又瘦身了约 800K。另外一些长时间不用的 UI 界面没有做成独立 Bundle而是堆在resources目录下。我把它们移到自定义 Bundle 中首包从 6.8M 降到 4.6M。7.4 第四步最终构建验证最后还剩 4.6M距离目标 4M 只差一步。我进一步调整了压缩纹理的大小ASTC 8×8并对部分 UI 做了二次压缩最终包体稳定在 3.9M 左右。这个过程中最费时间的其实是第一步的资源盘点因为需要逐个排查哪些资源体量大、哪些资源可以替换。但一旦摸清底细后续的优化就是水到渠成的事情。8. 长期维护如何让包体优化不再是“一次性手术”很多团队做完一次包体瘦身发布版本后就再也不管了。结果到了下个版本新加了一批资源包体又悄悄涨回去了。包体优化应该是一种长期维护习惯而不是临时抱佛脚。8.1 构建前资源清单检查我的团队现在固定会在每次发版前做一次“资源健康检查”。具体内容包括检查是否有超过 500KB 的图片资源未经压缩直接进入构建检查是否有超过 200KB 的音频直接放在主包检查是否存在重复引用或未清理的废弃资源检查是否有较大体积的资源可以拆到分包这个检查不需要额外写脚本日常维护时多看一眼资源和构建产物就能做到。8.2 代码提交时的体积意识做版本迭代时新增资源是不可避免的。关键在于新增资源时是否有意识判断这个资源是首包需要的还是可以延迟加载或分包加载我将这个判断过程总结成三个问题玩家进入游戏第一眼能看到这个资源吗如果不加载这个资源玩家能否玩到核心玩法这个资源能否通过图集合并或压缩算法进一步瘦身如果三个问题的答案都是“否”那这类资源就是典型的可拆分资源应该做延迟加载或分包处理。8.3 自动化监控进阶如果你的项目比较大团队人数也多纯靠人工检查容易遗漏。可以考虑写一个简单的脚本读取构建产物目录统计各 Bundle、各类型文件的大小并输出报告。这样每次构建后跑一次脚本看到数值异常就能快速定位问题。脚本的思路并不复杂遍历build目录下的assets文件夹按扩展名分类统计字节数输出到控制台或生成一个 HTML 报告。我用 Node.js 写过一版几百行代码能自动过滤掉引擎自带文件比如assets/main/textures是引擎纹理直接显示项目自产资源的体积分布。提示长期维护包体优化的最终目标不是把每个版本都压到 4M 以下有些项目玩法复杂资源必然多而是保证你清楚地知道“每个资源为什么会存在、它占了多大体积、玩家何时需要加载它”。有了这份意识包体失控的可能性就会大大降低。9. 最后分享几个我实测有效的“偏方”上面讲的都是正道下面这几个是我在实践中摸索出来的偏方不一定适合所有项目但很多场景下确实有效。9.1 动态创建简单图形代替图片资源如果你的游戏里有很多简单几何图形圆形、矩形、圆角矩形等完全可以用代码动态创建。CocosCreator 的Graphics组件可以绘制基本的几何图形配合九宫格拉伸和一些基础的双色混色能替代不少简单的 UI 素材。我在一个项目里用 Graphics 动态绘制血量条、进度条、按钮背景直接把一整张 UI 图集省掉了包体砍掉了差不多 500K。前提是你对这些 UI 元素的视觉要求不高能接受较低的花样。9.2 使用 Font 的文本替代方案如果游戏里需要显示大量文字比如说明性文本、公告直接使用系统字体或引擎内置字体比打包自定义字体文件小得多。自定义字体动辄 2M-10M而系统字体在微信小游戏里是运行时加载的不占包体。当然如果你的游戏有比较强的风格化字体需求可以尝试做字库裁剪——只保留游戏里实际用到的字符能大幅降低字体文件体积。我见过有项目把 3M 的字体文件裁剪到 200K 左右视觉效果还完全保持一致。9.3 善用引擎自带的远程加载能力前面提到过远程加载资源这里再补充一个更具体的场景运营活动资源。比如节日礼包、限时活动的背景图这类资源是临时的活动结束就不需要了。把它们放到远程服务器上玩家按需加载不但不占主包空间活动更新时也不用强制重新发包可谓一举两得。实际开发中我见过不少团队把活动资源直接硬塞进主包导致每次活动上线都要等审核、等更新玩家体验也很差。改用远程资源后这个问题彻底解决。10. 写在最后包体优化没有银弹做包体优化这么多年最大的一个体会就是没有哪一招能包治百病但每一项优化叠加起来效果就非常可观。一个 6M 的项目通常可以通过下面这些手段压到 4M 以内图片压缩 压缩纹理减少 30%-50%音频格式调整 采样率降低减少 40%-60%图集合并减少 10%-20%分包 远程资源主包减少 30%-50%代码和资源引用清理减少 5%-10%这些减幅单独看不惊人但叠加起来包体从 6M 降到 3.5M 是非常现实的。我自己的做法是每次版本开发结束后都会把“包体优化”和“功能开发”放在同等的优先级上而不是等包体超了再亡羊补牢。养成这个习惯后你会发现 4M 这个门槛其实没那么可怕。如果你正在被 CocosCreator 2.x 或 3.x 的包体问题困扰希望这篇文章能给你一些启发。先去翻翻你的构建产物看看哪些资源是“体积大王”从那里开始动手吧。
返回列表