CocosCreator Label优化

 1.需要修改引擎,参阅引擎定制工作流程

2.BITMAP缓存优化原理,参阅【乐府】突破Label的缓存模式之(1) BITMAP – Creator – Cocos中文社区

3.查看动态合图的api

运行时在console中输入

开启

cc.dynamicAtlasManager.showDebug(true);

关闭

cc.dynamicAtlasManager.showDebug(false);

4.修改记录

cocos2d/core/renderer/utils/label/ttf.js


_calDynamicAtlas (comp) {

        if(comp.cacheMode !== Label.CacheMode.BITMAP) return;

        let frame = comp._frame;

        // Delete cache in atlas.

        // mrlizs

        // deleteFromDynamicAtlas(comp, frame);

        if (!frame._original) {

            frame.setRect(cc.rect(0, 0, _canvas.width, _canvas.height));

        }

        // mrlizs

        // 给frame的texture计算一个新的_uuid值

        frame._texture._uuid = comp.string + "_" + comp.node.color + "_" + comp.fontSize + comp.fontFamily;

        this.packToDynamicAtlas(comp, frame);

    }

cocos2d/core/renderer/utils/utils.js

deleteFromDynamicAtlas (comp, frame) {

        if (frame && !CC_TEST) {

            if (frame._original && dynamicAtlasManager) {

                // mrlizs

                // dynamicAtlasManager.deleteAtlasSpriteFrame(frame);

                frame._resetDynamicAtlasFrame();

            }

        }

    }

cocos2d/core/renderer/utils/dynamic-atlas/atlas.js

insertSpriteFrame (spriteFrame) {

        let rect = spriteFrame._rect,

            texture = spriteFrame._texture;

            // mrlizs

            // info = this._innerTextureInfos[texture._id];

        // 在这里通过_uuid来判断重用性

        // this._dynamicTextureRect 增加的一个字典用来记录uuid与texture的映射关系

        let info = this._dynamicTextureRect[texture._uuid];

        let sx = rect.x, sy = rect.y;

        if (info) {

            sx += info.x;

            sy += info.y;

        }

        else {

            let width = texture.width, height = texture.height;        

            if ((this._x + width + space) > this._width) {

                this._x = space;

                this._y = this._nexty;

            }

            if ((this._y + height + space) > this._nexty) {

                this._nexty = this._y + height + space;

            }

            if (this._nexty > this._height) {

                return null;

            }

            // texture bleeding

            if (cc.dynamicAtlasManager.textureBleeding) {

                // Smaller frame is more likely to be affected by linear filter

                if (width <= 8 || height <= 8) {

                    this._texture.drawTextureAt(texture, this._x-1, this._y-1);

                    this._texture.drawTextureAt(texture, this._x-1, this._y+1);

                    this._texture.drawTextureAt(texture, this._x+1, this._y-1);

                    this._texture.drawTextureAt(texture, this._x+1, this._y+1);

                }

                this._texture.drawTextureAt(texture, this._x-1, this._y);

                this._texture.drawTextureAt(texture, this._x+1, this._y);

                this._texture.drawTextureAt(texture, this._x, this._y-1);

                this._texture.drawTextureAt(texture, this._x, this._y+1);

            }

            this._texture.drawTextureAt(texture, this._x, this._y);

            this._innerTextureInfos[texture._id] = {

                x: this._x,

                y: this._y,

                texture: texture

            };

            // mrlizs

            this._dynamicTextureRect[texture._uuid] = {

                x: this._x,

                y: this._y

            };

            this._count++;

            sx += this._x;

            sy += this._y;

            this._x += width + space;

            this._dirty = true;

        }

        let frame = {

            x: sx,

            y: sy,

            texture: this._texture

        }

        

        this._innerSpriteFrames.push(spriteFrame);

        return frame;

    },

    // mrlizs

    fetchSpriteFrame(spriteFrame) {

        let texture = spriteFrame._texture;

        let info = this._dynamicTextureRect[texture._uuid];

        if (!info) {

            return null;

        }    

        let rect = spriteFrame._rect;

        let sx = rect.x + info.x, sy = rect.y + info.y;

        let frame = {

                x: sx,

                y: sy,

                texture: this._texture

            }

        if (!this._innerSpriteFrames.includes(spriteFrame)) {

            this._innerSpriteFrames.push(spriteFrame);

        }

        return frame;

    },

    deleteInnerTexture (texture) {

        if (texture && this._innerTextureInfos[texture._id]) {

            delete this._innerTextureInfos[texture._id];

            // mrlizs

            delete this._dynamicTextureRect[texture._uuid];

            for(let i = 0, n = this._innerSpriteFrames.length; i < n; i++){

                if (this._innerSpriteFrames[i]._texture._uuid == texture._uuid){

                    this._innerSpriteFrames.splice(i,1);

                    break;

                }

            }

            this._count--;

        }

    }

cocos2d/core/renderer/utils/dynamic-atlas/manager.js

insertSpriteFrame(spriteFrame) {

        if (CC_EDITOR) return null;

        if (!_enabled || _atlasIndex === _maxAtlasCount ||

            !spriteFrame || spriteFrame._original) return null;

        if (!spriteFrame._texture.packable) return null;

        // mrlizs

        for (let i = 0, n = _atlases.length; i < n; i++) {

            let atlas = _atlases[i];

            // 如果能从当前图集中找到相同_uuid的图集块,则重用

            let frame = atlas.fetchSpriteFrame(spriteFrame);

            if (frame != null) return frame;

        }

        let atlas = _atlases[_atlasIndex];

        if (!atlas) {

            atlas = newAtlas();

        }

        let frame = atlas.insertSpriteFrame(spriteFrame);

        if (!frame && _atlasIndex !== _maxAtlasCount) {

            atlas = newAtlas();

            return atlas.insertSpriteFrame(spriteFrame);

        }

        return frame;

    }

5.效果

修改前,原引擎对label的缓存是在onEnable时都会把上一次已缓存的纹理清掉然后重新创建,而实际上动态合图里有大量重复的label纹理,运行cc.dynamicAtlasManager.showDebug(true);

时可以看到合图内容。

修改后,首先不再清掉动态合图里的缓存纹理,然后label的纹理会先去动态合图中找已经存在的图块,如果存在则复用,不存在再创建。

本文为原创文章,转载请注明出处!