欢迎光临
我们一直在努力

Cocos Creator 图集制作全攻略:从散图到性能优化一步到位

1. 引言

在 Cocos Creator 中,图集(Atlas)是提升渲染性能、减少 Draw Call 的关键手段。本文以 Cocos Creator 2.2.2 为例。为什么用2.2.2举例,因为本人现在修改的是一款很老的棋牌项目,所以就顺便了,从图片资源准备、图集配置、生成与使用、动态合图四个方面,完整讲解图集的制作流程。

2. 图集的基本概念

图集是将多张零散的小图合并到一张大图上,并配套生成一份描述每张小图位置、尺寸、旋转等信息的元数据文件。渲染时,引擎只需一次性提交这张大图,就能绘制多个小图,从而显著减少 Draw Call。

在 Cocos Creator 2.2.2 中,图集由以下两部分组成:

  • 纹理文件:合并后的大图,常见格式为 PNG 或 JPG。
  • 图集元数据:记录每张小图在大图中的矩形区域、旋转状态、是否镂空等信息,通常以 .plist 或 .json 格式保存。

3. 图片资源准备

在制作图集之前,需要先整理好散图资源。建议遵循以下规范:

  • 所有小图统一放在同一个目录下,例如 assets/textures/ui。
  • 小图尺寸尽量规整,避免出现过大或过小的极端尺寸。
  • 图片命名使用英文小写加下划线,例如 btn_start.png、icon_coin.png。
  • 避免使用重复名称,防止图集生成时互相覆盖。

准备好散图后,在 Cocos Creator 2.2.2 的资源管理器中选中这些图片,即可开始配置图集。

4. 创建图集资源

在 Cocos Creator 中,创建图集有两种常用方式:自动图集和手动图集。下面分别介绍它们的制作步骤和关键参数。

4.1 自动图集

自动图集是最常用的方式,操作步骤如下:

  • 在资源管理器中,右键点击资源目录,选择「新建」→「自动图集配置」。
  • 创建完成后,会生成一个 .pac 配置文件。
  • 选中该配置文件,在属性检查器中设置图集参数。
  • 将需要打包的散图目录拖入「包含文件夹」列表。
  • 点击属性检查器上方的「生成」按钮,即可生成图集。
  • 自动图集配置的核心参数说明如下:

    参数说明
    包含文件夹 指定需要打包进图集的图片目录,可添加多个。拖入目录后,该目录下的所有散图都会参与合图。
    最大宽度 / 最大高度 图集纹理的最大尺寸,默认 2048 x 2048。当散图总尺寸超出限制时,引擎会自动拆分为多张图集。
    内边距 每张小图之间的间距,建议设置为 2。过小的内边距会导致相邻小图采样时发生边缘渗色,出现黑边或白边。
    允许旋转 是否允许小图旋转 90 度以提升空间利用率,默认开启。开启后能更紧凑地排列小图,减少图集面积浪费。
    输出格式 支持 png、jpg 等格式。包含透明通道的 UI 图标建议使用 png,纯不透明的大图可考虑 jpg 以减小体积。

    4.2 手动图集

    手动图集适合对图集布局有特殊要求的场景,例如需要精确控制某张图的位置。操作步骤如下:

  • 在资源管理器中,右键点击资源目录,选择「新建」→「图集」。
  • 创建后会生成一个 .atlas 文件。
  • 双击打开图集编辑器,将散图从资源管理器拖入图集编辑窗口。
  • 手动调整每张小图的位置和排列方式。
  • 保存后,图集资源即生成完毕。
  • 手动图集适合小规模、需要精细控制的资源,日常开发中更推荐使用自动图集。

    5. 图集生成与验证

    在构建之后生成的图就是图集了

    6. 在代码中使用图集

    图集生成后,在场景编辑器或代码中引用小图的方式与普通散图一致。Cocos Creator 2.2.2 会自动将图集中的小图识别为独立资源,开发者无需手动指定图集路径。

    在代码中动态加载图集中的小图,可以使用以下方式:

    // 加载图集中的小图
    cc.resources.load("textures/ui/btn_start/spriteFrame", cc.SpriteFrame, function (err, spriteFrame) {
    if (!err) {
    this.node.getComponent(cc.Sprite).spriteFrame = spriteFrame;
    }
    });

    需要注意的是,图集中的小图路径以图集内的小图名称为准,而不是散图在项目中的原始路径。

    下面给出一个完整的实战示例:动态加载图集并切换多个 Sprite 的 SpriteFrame,包含资源加载、错误处理和内存释放的完整流程。

    // SpriteSwitcher.js
    // 实战示例:动态加载图集并切换多个 Sprite 的 SpriteFrame
    cc.Class({
    extends: cc.Component,

    properties: {
    // 需要切换的 Sprite 节点数组,在编辑器中拖入
    spriteNodes: {
    default: [],
    type: [cc.Node]
    },
    // 图集中小图名称数组,例如 ["icon_coin", "icon_star", "icon_heart"]
    spriteFrameNames: {
    default: [],
    type: [cc.String]
    }
    },

    onLoad: function () {
    // 缓存已加载的 SpriteFrame,避免重复加载
    this._spriteFrames = [];
    // 当前显示的小图索引
    this._currentIndex = 0;
    // 标记资源是否已加载完成
    this._loaded = false;

    // 开始加载图集中的小图
    this._loadSpriteFrames();
    },

    // 加载图集中的所有小图
    _loadSpriteFrames: function () {
    var self = this;
    var names = this.spriteFrameNames;
    var loadedCount = 0;

    // 遍历所有需要加载的小图名称
    for (var i = 0; i < names.length; i++) {
    // 拼接图集内小图的完整路径
    var path = "textures/ui/" + names[i] + "/spriteFrame";

    // 动态加载 SpriteFrame 资源
    cc.resources.load(path, cc.SpriteFrame, function (err, spriteFrame) {
    if (err) {
    // 错误处理:加载失败时打印错误信息
    cc.error("加载 SpriteFrame 失败: " + path + ", 错误: " + err);
    return;
    }

    // 加载成功,缓存 SpriteFrame
    self._spriteFrames.push(spriteFrame);
    loadedCount++;

    // 所有资源加载完成后,显示第一张小图
    if (loadedCount === names.length) {
    self._loaded = true;
    self._applySpriteFrame(0);
    }
    });
    }
    },

    // 将指定索引的 SpriteFrame 应用到所有 Sprite 节点
    _applySpriteFrame: function (index) {
    if (!this._loaded || index < 0 || index >= this._spriteFrames.length) {
    return;
    }

    var spriteFrame = this._spriteFrames[index];

    // 遍历所有 Sprite 节点,切换 SpriteFrame
    for (var i = 0; i < this.spriteNodes.length; i++) {
    var sprite = this.spriteNodes[i].getComponent(cc.Sprite);
    if (sprite) {
    sprite.spriteFrame = spriteFrame;
    }
    }

    this._currentIndex = index;
    },

    // 切换到下一张小图
    next: function () {
    if (!this._loaded) {
    return;
    }
    var nextIndex = (this._currentIndex + 1) % this._spriteFrames.length;
    this._applySpriteFrame(nextIndex);
    },

    // 切换到上一张小图
    prev: function () {
    if (!this._loaded) {
    return;
    }
    var prevIndex = (this._currentIndex – 1 + this._spriteFrames.length) % this._spriteFrames.length;
    this._applySpriteFrame(prevIndex);
    },

    // 组件销毁时释放加载的资源,避免内存泄漏
    onDestroy: function () {
    for (var i = 0; i < this._spriteFrames.length; i++) {
    // 释放 SpriteFrame 资源引用
    cc.assetManager.releaseAsset(this._spriteFrames[i]);
    }
    this._spriteFrames = [];
    this._loaded = false;
    }
    });

    上述示例的关键步骤说明:

    • 资源加载:通过 cc.resources.load 按图集内小图名称拼接路径,逐个加载 SpriteFrame,并缓存到数组中。
    • 错误处理:加载回调中判断 err,失败时打印错误日志并返回,避免后续逻辑访问空资源。
    • 切换 SpriteFrame:_applySpriteFrame 方法将指定索引的 SpriteFrame 应用到所有目标 Sprite 节点,支持多个 Sprite 同步切换。
    • 内存释放:在 onDestroy 中通过 cc.assetManager.releaseAsset 释放已加载的 SpriteFrame,防止组件销毁后资源残留导致内存泄漏。

    7. 动态合图

    除了预先制作图集,Cocos Creator 2.2.2 还提供了动态合图能力。动态合图会在运行时自动将散图合并到一张动态图集中,适合无法预先确定图片集合的场景。

    动态合图默认开启,可以通过以下代码控制:

    // 开启动态合图
    cc.dynamicAtlasManager.enabled = true;

    // 关闭动态合图
    cc.dynamicAtlasManager.enabled = false;

    动态合图虽然方便,但也有一些限制:

    • 动态图集有最大尺寸限制,超出后无法继续合入。
    • 动态合图会增加运行时内存占用。
    • 部分特殊纹理(如大尺寸图片、带旋转的纹理)可能无法参与动态合图。

    因此,对于 UI 界面等固定资源,建议优先使用预先制作的图集;对于运行时动态生成的图片,再考虑动态合图。

    8. 常见问题与注意事项

    8.1 图集生成后小图显示黑边

    这通常是因为内边距设置过小,导致相邻小图采样时发生渗色。解决方法是将「内边距」调整为 2 或更大,然后重新生成图集。

    8.2 图集尺寸超出限制

    当散图数量较多或单张图片较大时,图集可能超出最大尺寸限制。此时引擎会自动拆分为多张图集,开发者无需手动处理,但需要注意内存占用会相应增加。

    8.3 修改散图后图集未更新

    修改散图后,需要重新点击「生成」按钮,图集才会更新。如果使用自动图集,也可以在资源管理器中对图集配置执行「重新生成」操作。

    8.4 图集与散图同时存在

    如果同一张图片既存在于图集中,又作为散图被引用,Cocos Creator 2.2.2 会优先使用图集中的资源。建议在项目规范中明确资源管理方式,避免重复引用。

    9. 总结

    本文基于 Cocos Creator 2.2.2,介绍了图集制作的核心流程:从散图准备、自动图集与手动图集的创建、参数配置、生成验证,到代码中的使用方式,以及动态合图的适用场景。掌握图集制作,可以有效减少 Draw Call,提升游戏运行性能。

    在实际项目中,建议优先使用自动图集管理 UI 资源,并合理设置内边距和最大尺寸,同时结合动态合图处理运行时动态图片,从而在性能和开发效率之间取得平衡。

    赞(0)
    未经允许不得转载:171主机测评 » Cocos Creator 图集制作全攻略:从散图到性能优化一步到位
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址