最近在Cocos Creator的项目中遇到一个诡异的问题。
使用cc.loader.loadRes
后,会出现图片花屏(变成了一张图集),和getTexture()
获取尺寸错误(总是2048*2048)的问题。
研究之后,发现有关SpriteFrame的使用,这些坑你可能不知道。
Cocos Creator 2.x 的运行时图集合并机制
经过测试发现,Cocos Creator 2.x 版本在运行时有一套自动图集合并机制。(Dynamic Atlas Manager)
在调用cc.loader.loadRes
加载图片资源时,如果第二次加载同一资源,那么该资源会自动合入一张运行时创建的 2048*2048 的大图集中。
如此,对于运行时动态加载并且重复使用的小碎图,可以有效的减少Draw Call。
带来的问题
不再适合用getTexture()
去获取图片纹理
如上,当资源第二次加载后,getTexture()
获取到的就不是小图的纹理,而是对应自动图集的 2048*2048 的RenderTexture
。
因此,如果通过这个纹理来获取图片的尺寸等信息,就是错误的。(永远是2048*2048)
如果再用setTexture
将这个纹理赋给其它的SpriteFrame
,当然就会出现花屏的问题了。(显示的是一张大图集)
解决方案
获取加载后的图片尺寸
cc.loader.loadRes('xxx', cc.SpriteFrame, (err, res)=>{
// 获取图片原始尺寸(不裁剪透明像素)
res.getOriginalSize().width;
res.getOriginalSize().height;
// 获取图片裁剪透明像素后的尺寸
res.getRect().width;
res.getRect().height;
})
给其它SpriteFrame赋值
提供两种方案解决
方案一:关闭运行时自动图集(不推荐)
cc.dynamicAtlasManager.enabled = false;
方案二:setTexture时,传入完整的SpriteFrame子纹理信息
由于loadRes
返回的是SpriteFrame,即便对应的Texture是大图集,但仍然保存着子纹理的位置和尺寸信息。
在setTexture
时,将其余信息一并传入,等同于设置子纹理。
cc.loader.loadRes('xxx', cc.SpriteFrame, (err, res)=>{
// target 是要设置的目标SpriteFrame
target.setTexture(
res.getTexture(),
res.getRect(),
res.isRotated(),
res.getOffset(),
res.getOriginalSize()
);
})
(正文完)