新发一个帖子吧 加载自定义后缀和无后缀图片

1. 自定义后缀图片加载

总结优化一下我的上一个帖子如何加载自定义后缀图片


思路很简单 无非就是在downloader下载器中注册自定义后缀资源的处理方式官方手册-下载与解析

注: 一般来说下载器的使用方式如下

//拓展自定义后缀格式文件加载
cc.assetManager.downloader.register({
    //表格文件
    '.xlsx': cc.assetManager.downloader._downloaders['.bin'],
    //压缩文件
    '.zip': cc.assetManager.downloader._downloaders['.bin'],
    '.rar': cc.assetManager.downloader._downloaders['.bin'],
    //加密文件
    '.abandon': cc.assetManager.downloader._downloaders['.bin'],
    '.ab': cc.assetManager.downloader._downloaders['.bin'],
});

我们先以.bin的处理方式加载二进制数据(这里可以进行数据解密流程)
之后封装个创建精灵帧方法 buffer->blob->dataUrl->img->texture->spriteFrame
(image和imageBitmap不太懂 好像需要判断
cc.macro.ALLOW_IMAGE_BITMAP 和 cc.sys.capabilities.imageBitmap)


如果到了这一步直接结束下载流程 会发现创建的资源是长这样的(一开始就是在这一步卡了很久)

后面就是翻引擎底层代码 翻啊翻发现还有个assetManager.factory资产加工厂
在资源创建的最后一步负责加工 即把asset加工为texture

使用方式很简单 也和下载器的使用差不多 分为两步

  1. 在创建精灵帧的完成回调中进行assetManager.factory.register注册
  2. 也是我们整个流程的最后一步 在加载资源的load回调中进行assetManager.factory.create创建(最后一步加工)

这样 我们就完整地走完了整个的资源加载流程 从下载 解析(这部分我们自己完成了) 以及最后的加工

可能有人会有疑问 你一开始作为二进制数据下载了 那么直接把创建精灵帧封装到加载资源的load里不就完事了吗
可以是可以 其实一开始我也是这样做的 只不过为了load接口的单一性和一致性 没有选择往里塞东西

2. 无后缀图片的加载

还是我发的一个帖子 没有大佬解惑只好自己来

写到这里其实有点累了 上面简直是回调地狱 直接上代码贴图


这个就简单多了 一共就三步

  1. 拿到nativeUrl
  2. 加载二进制数据
  3. 创建精灵帧

无后缀图片的特殊性在于 你连注册自定义后缀都注册不了
所以不用走注册拦截了 直接用下载器下载吧 这里就迎来了第二个难点 nativeUrl如何获取


assetManager.utils.getUrlWithUuid这个api能够将uuid转化为nativeUrl`
而uuid可以直接通过asset对象的_uuid属性拿到 或者通过在bundle下的路径拿到资源信息

剩下就是对自己的load进行封装 把上面加载自定义后缀也封装进来
设置一个ext后缀参数 然后根据不同的后缀选择不同的加载策略 这里就不写了 我也还没封装

web preview测试通过 然而web构建后发现只有import的json 没有native的无后缀文件
似乎无后缀文件不会参与构建吗??
宣告失败哈哈哈 有没有大佬解惑下 从来没有了解过这一块

对于新手来说本次探索最主要的收获就是对拦截操作 下钩子 函数传入回调函数作参数 多积累了一点点经验

大佬66666

1赞

大佬 无后缀加载还有一点问题 本地预览正常 但是web构建发布的里面无后缀文件好像没被打进去 :joy:你知道是咋回事吗

我也不知道啊 :sweat_smile:

1赞

我传了demo 代码不多的 主要还是构建发布后 无后缀文件没有被打包进去的问题 大佬有时间的话帮忙看看

如果说我这边无需自定义后缀,只需要对png进行加解密,并且是通过blob进行一个简单位移,如何去构建cc.assetManager.downloader.register写法

    cc.assetManager.downloader.register(".png",(url, options,callback)=>{
        //加载二进制数据
        cc.assetManager.downloader["_downloader"][".bin"](url, options, (err,buffer:ArrayBuffer)=>{
            const b:Blob = decryptBlobFunc(buffer,"xxx");
           //然后咋整直接callback吗?第二个参数咋传 传blob?
          callback(err,b);
        })
    })
1赞

不管怎么hook下载和解析 只要hook了就不能直接正常加载到spriteFrame了 我是通过factory最终加工得到和正常加载一样的资源

给你附上我写的接口声明 希望有帮助

interface Downloader {
    /**image元素下载处理 */
    downloadDomImage: (url: string, opts: Record<string, any>, onComplete: (err: Error, img: HTMLElement) => void) => void;
}
interface Parser {
    /**解析图片文件 */
    parseImage: (file: Blob, opts: Record<string, any>, onComplete: (err: Error, img: ImageBitmap | HTMLImageElement) => void) => void;
}

就是说一旦干预了资源的加载管线,就要自己去构建和维护好对应的精灵资源对象是吧

1赞

对 至少我尝试下来是这样的 资源的引用计数和释放有没有影响我就不清楚了 可能也需要自己维护

1赞

当然也不是非要在下载与解析这里hook的 可以直接按.bin加载你的加密后缀图片为二进制数据(如果不是全部图片都加密我觉得还是改个后缀区分一下比较好) 然后把解密和解析操作放到你自己封装的load里 解密完再由二进制数据生成spriteFrame 这样回调能少点 不然搁那里面真的是回调地狱

放进bundle或者resources中也不能打进去?

1赞

对 上面有demo 我测试手动放进去没问题 如果实在没办法就只能hook构建流程了

那是不是得看下数据源是长什么样,不然构建的数据格式不对,或者部分数据源少了,也不知道会引发啥 :sweat_smile:

1赞

我是这样转换数据格式的

我好像知道为啥打不进包里面了,在打包的过程中,解析不出来你自定义的格式,你可能真的需要hook下

1赞

:kissing_smiling_eyes: