k8w.io
CocosCreator loadRes后花屏和图片尺寸错误的解决
2019-03-12作者:k8w

最近在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()
    );
})
(正文完)
留言(0条)
发表新留言
您的大名:
必填
电子邮箱:
不公开,仅用于向你发送回复