使用 Zip 加速 CocosWeb 加载

就是我现在把图片都放进压缩包里,就是怎么能解析到对应的组件上而不是还得通过找对应的组件来设置

记一下吧。

想在编辑器编辑好界面,然后构建完之后再zip所有图片,加载的时候先加载zip包是吧?
如果是这样的话

let downloadImage = function (url, options, onComplite) {
            //url : assets/native/d1/d15232231231231231231.png
            //从zip包加载对应文件
        }

        cc.assetManager.downloader.register({ ".png": downloadImage, ".jpg": downloadImage, ".webp": downloadImage });

这样应该可以,可以试一下

我就是这样试了,现在是到这里
let downloadImage = function (url, options, onComplite) {
这里还得解析zip包解压出来的文件找对应的组件,还是说直接 直接根据**url,**从zip包缓存里取对应的文件就可以了
}

直接从zip包读取到创建出来后回调onComplite就可以了

let downloadImage = function (url, options, onComplite) {
if(zipCache.has(url)){
这里还得创建对应的图片然后赋值给sprite吗,这样的话还是得找到具体的sprite组件
onComplete();
}

let downloadImage = function (url, options, onComplite) {
            //url : assets/native/d1/d15232231231231231231.png
            //从zip包加载对应文件
        }

        cc.assetManager.downloader.register({ ".png": downloadImage, ".jpg": downloadImage, ".webp": downloadImage });

你挂在sprite上的图片加载的时候走的就是这里啊,不太理解你说的要找具体的sprite组件是什么意思,我有点懵

我的意思下载zip后,在dowloadImage函数里直接读取对应的png,然后执行complete就可以正常预览吗,还是还得在里面处理通过cc.assetManager.factory.create(tempImageName + Date.now(), imageData, imageExt, {}, (err, texture: cc.Texture2D) => {
if (err) {
return;
}
})这个来赋值到sprite上

在web上,可以考虑服务端开启http/2,可以大幅提高了并发请求的能力

 let downloadImage = function (url, options, onComplite) {
            //url : assets/native/d1/d15232231231231231231.png
            //从zip包加载对应文件
            let fileName = cc.path.basename(url);
            let zipData //加载好的zip文件
            let data = zipData.files[fileName];
            let extName = fileName.split('.').pop();//文件后缀
            switch (extName) {
                case 'png':
                case 'jpg':
                case 'bmp':
                case 'jpeg':
                case 'gif':
                case 'ico':
                case 'tiff':
                case 'webp':
                case 'image':
                    let tempImageName = fileName.split('/').pop();
                    let imageExt = `.` + tempImageName.split('.').pop();
                    let asyncType = cc.sys.capabilities.imageBitmap && cc.macro.ALLOW_IMAGE_BITMAP ? 'blob' : 'base64';
                    data.async(asyncType).then((result) => {
                        //@ts-ignore
                        cc.assetManager.parser.parseImage(result, {}, (err, imageData) => {
                            if (err) {
                                return;
                            }
                            if (imageData) {
                                //@ts-ignore
                                cc.assetManager.factory.create(tempImageName + Date.now(), imageData, imageExt, {}, (err, texture: cc.Texture2D) => {
                                    if (err) {
                                        return;
                                    }
                                    onComplite && onComplite(null, texture);
                                })
                            }
                        });
                    });
                    break;
            }
        }

        cc.assetManager.downloader.register({ ".png": downloadImage, ".jpg": downloadImage, ".webp": downloadImage });

具体没测,大概这样

朋友非常感谢,我去看看

试了一下图片加载的不对,成功进场景了但是所有的图片都显示不出来

发个demo看看

说实话,引擎出一个功能就是,可以给资源文件夹或者bundle打勾,然后打勾的资源都在打包的时候打成压缩包的这样一个功能会不会很难?我就想问一下,我觉得这个功能有时候挺实用的,即便是不放远程,包体也能进一步缩小,也能避免上面说到的并发问题,肯定会有性能消耗,但是我觉得看不同项目的利弊,不管怎么说我觉得这样的功能很赞! :rofl:

1赞

Demo.zip (1.6 MB)
试试这个

厉害,看起来不错

得把zip 改成bin吗

不需要,只是以.bin格式去加载,文件不需要改名

好的明白了谢谢

看起来应该是不难,小游戏的是有支持可以把bundle的压缩类型设置为zip,原生的没支持。
image

然后这玩意有个问题,之前在3.6.2版本遇到的(升级到3.8.3之后没再测试过):

  • 保存到临时目录的是zip文件
  • 保存到缓存目录的是解压后的文件
  • 即直接从临时目录解压到缓存目录

这样子会有个问题,就是当处于临界状态,缓存目录的可用空间小于解压后的文件总大小会导致解压失败,之后加载这部分资源就会失败。
猜测可能是由于一部分已经解压到缓存目录所以判定全部在缓存目录里,但是实际读取的时候又找不到对应的文件导致的。这个有空的蛮关注一下 @max