如何判断资源名是不是在这个bundles集合里

判断资源是不是在这个bundles
image

如想判断light.jpeg是否在某个bundle里代码:

var bundles = assetManager.bundles;
for(var i=0;i<bundles.length;i++){
if(bundles[i]["light.jpeg"]){ //这里怎么判断是在具体哪个bundle里呢?
 }

}

感觉不太科学

你现在理解的资源都是一个文件,比如图片 jpg

但是,实际的资源可能是由多个文件组成的,比如一个spine是由3个文件组成的,缺一不可

比如

  • spine.png
  • spine.json
  • spine.atlas

这种情况下,同名文件有3个,这种情下,难道判断3次同个文件名字吗?或者说判断 3个资源吗,很奇怪的

鉴于资源不是一个文件就可以,资源之间是存在依赖关系,资源是一套的这种情况

所以根据资源名字判断是否在 bundle 里面 是一个感觉很奇怪的问法?

一般都是直接load某个资源,load到就存在,load不到就不存在

Cocos Creator 3.8 API - Bundle

API 文档是个好东西。

就是子游戏A与子游戏B 都loadbundle后,想传文件名直接load到而不是assetManager.getBundle(‘子游戏B’).load(name) 先要知道这个资源在哪个bundle里,所以这里想封装接口遍历一下已加载的所有bundles,看看资源在哪个bundle里,然后load。

这样设计项目所有资源名字必须保证唯一,所有资源的 load统一走封装好的接口,无须关心load哪个bundle,只要传load的资源文件名就可以load了

看不懂 :sweat_smile: :sweat_smile: :sweat_smile: :sweat_smile:

   res.load(a.png)      我给你我想要的url 我不想管我到底是在哪个bundle  ,你自己给我找出来

那如果同一个名字在多个bundle上出现,怎么处理呢?

比如有10个bundle,每个bundle开发规范都是一样

bundle-a
  ┣ prefabs
  ┣ scenes
  ┣ textures
  ┣ materials
  ┣ effects
  ┗ scripts
bundle-b
  ┣ prefabs
  ┣ scenes
  ┣ textures
  ┣ materials
  ┣ effects
  ┗ scripts

其中都有 textures/slogan.png

这种的话,你不如直接放 resources,就不要用 bundle 这个概念了

1赞

先读取 bundle, 然后读取 bundle里的文件。 就是传 url。 跟你说的可能有区别。 你必须知道是哪个bundle,才能在这个bundle用 url 。 你url可以一样,可以乱来。 但是你bundle必须分清楚

如楼上,你这种方式了是很不建议的
其次了,要实现也不是不可以,可以看下Bundle的API

        const info = bundle?.getInfoWithPath('a');
        const info2 = bundle?.getInfoWithPath('list/Item');
        // 没有为null, 有为资源信息(解析前的信息)
        console.log('info=', info, 'info2=', info2);

啪啪一顿搞 :sweat_smile:

/*
//GF.BundleCtr.getInstance().getBundleInfo("light");
通过资源名字获取该资源所属的包信息,如:包名,实际路径
{
    "bundleName":"Subitem_1002",
    "path":"res/light"
}
*/
public getBundleInfo(name) {
    var bundles = assetManager.bundles["_map"];
    if(bundles){
        for (const key in bundles) {
            if (Object.prototype.hasOwnProperty.call(bundles, key)) {
                const bundleName = key;
                const pathsMap = bundles[key]["_config"]["paths"]["_map"];
                for (const mKey in pathsMap) {
                    if (Object.prototype.hasOwnProperty.call(pathsMap, mKey)) {
                        let sp = mKey.split("/");
                        let lastName = sp[sp.length - 1];
                        if (lastName == name) {
                            return {
                                "bundleName": bundleName,
                                "path": mKey
                            };
                        }
                    }
                }
            }
        }
    }
   
}

进子游戏前自行判断,假如是Subitem_1002的总bundle,先执行 assetManager.loadBundle(“Subitem_1002”),之后子游戏代码中代码加载资源只用唯一的文件名就可以了,如:

var bundleInfo = GF.BundleCtr.getBundleInfo("light");
let bundle = assetManager.getBundle(bundleInfo.bundleName);
bundle.load(bundleInfo["path"],type,()=>{});//这三行代码再封装为统一的资源加载接口

如:

 GF.ResCtr.getInstance().createRes({ 
       name:"light.png",
       type:"自行判断.png属于imageAsset"
    });

动态加载资源就无须关心资源在resources里还是已加载bundle里了,只要调用GF.ResCtr.getInstance().createRes理论上传一个最简单的资源名light.png就可以了。

好处1:不用知道res属于哪个bundle再加载资源
好处2:不用传路径(后期经常调整目录)
(虽然方便但就是可能费性能,目前重复的可用缓存池)

你这一堆内部变量,看着就不靠谱

        assetManager.bundles.forEach(bundle => {
            const infos = bundle.getDirWithPath('/', Asset);
            infos.forEach((info) => {
                info.path;
                info.ctor;
            });
        });

forEach()写法千万级别运算没纯for快,有时简单的写法不一定效率最高呢

我就写这个意思 :innocent:

不过如果什么时候我一帧会循环千万次的话,我听你的用for