多图集合批分享(理论上全平台),无需修改引擎代码。

本人未使用CocosCreator发布线上项目,未经线上验证,仅供大家学习,目前暂不从事CocosCreator工作。

Cocos Creator 控制合批主要是在Batch2D中实现,检测的是(同一图集,同一材质,同一内存等),那么只要我们在提交前将数据搞成统一就好了。

function isInstanceOfAny(obj: any, types: any[]) {
        return types.some(type => obj instanceof type);
    }
const SupportComponents = [cc.SpriteFrame, cc.Label];

    const UIRenderer = cc.js.getClassByName(`cc.UIRenderer`);

    //更新材质

    UIRenderer.prototype[`updateMaterial${_}`] = UIRenderer.prototype.updateMaterial;

    UIRenderer.prototype.updateMaterial = function () {
//自动使用多图集合批材质

        if (!this._customMaterial
            && !this._bNotMultiAtlas
            && isInstanceOfAny(this, SupportComponents)
            && fw.multiAtlasesMaterial) {

            this.customMaterial = fw.multiAtlasesMaterial;

            return;

        }

        this[`updateMaterial${_}`]();
}

//更新渲染数据

    UIRenderer.prototype[`updateRenderer${_}`] = UIRenderer.prototype.updateRenderer;

    UIRenderer.prototype.updateRenderer = function () {

        this[`updateRenderer${_}`]();

        //材质是否正确

        if (!this._customMaterial
            || !fw.multiAtlasesMaterial

            || this._customMaterial != fw.multiAtlasesMaterial) {

            return;

        }

        let nTexIndex: number;

        const self: unknown = this;

        if (nIndex < nMaxIndex) {

            let dataHash: number;

            if (self instanceof cc.Sprite) {
                if (!self.spriteFrame) { return; }
                let tex: cc.__private._cocos_asset_assets_texture_base__TextureBase;
                dataHash = self.spriteFrame.texture.getHash();
                if (cache.has(dataHash)) {
                    nTexIndex = cache.get(dataHash);
                    hashFunc(self.renderData);
                } else {
                    self.customMaterial.setProperty(`texture${nIndex}`, self.spriteFrame.texture);
                    cache.set(dataHash, nIndex);
                    hashFunc(self.renderData);
                    nTexIndex = nIndex;
                    ++nIndex;
                }
            } else if (self instanceof cc.Label) {
                let tex: cc.__private._cocos_asset_assets_texture_base__TextureBase;
                if (self.ttfSpriteFrame) {
                    tex = self.ttfSpriteFrame.texture;
                    dataHash = tex.getHash();
                } else {
                    if (self.spriteFrame) {
                        if (self.spriteFrame instanceof cc.SpriteFrame) {
                            tex = self.spriteFrame.texture;
                            dataHash = tex.getHash();
                        } else {
                            //清理材质
                            this._customMaterial = null;
                            //标记
                            this._bNotMultiAtlas = true;
                            //刷新材质
                            this.updateMaterial();
                        }
                    }
                }
                if (dataHash) {
                    if (cache.has(dataHash)) {
                        nTexIndex = cache.get(dataHash);
                        hashFunc(self.renderData);
                    } else {
                        self.customMaterial.setProperty(`texture${nIndex}`, tex);
                        cache.set(dataHash, nIndex);
                        hashFunc(self.renderData);
                        nTexIndex = nIndex;
                        ++nIndex;
                    }
                }
            } else {
                console.warn(`暂不支持该类型多图集合批`, self);
            }

        } else {

            nTexIndex = nNoneIndex;

        }

        if (nTexIndex != V0) {

            if (self instanceof cc.Sprite) {

                if (self.type == cc.Sprite.Type.SLICED) {

                    for (let i = 0, uv = this.spriteFrame.uvSliced; i < uv.length; ++i) {

                        uv[i].u = nTexIndex * 1000 + uv[i].u % 1000;

                    }

                }

            }

            for (let i = 0, j = 3, r = this.renderData, v = r.chunk.vb; i < r.vertexCount; ++i, j += r.floatStride) {

                v[j] = nTexIndex * 1000 + v[j] % 1000;

            }

        }

    }

上面算是正确代码也算是伪代码,由于牵扯的东西也不少,我删减了,只留下了核心思想部分。

2赞