Creator web平台setting.js 文件详细解析和资源加载解析

这几天在优化web平台上单个场景加载速度,在论坛上搜索了很多资料,发现构建后文件夹中的import目录里面存的都是json文件,而且压缩率惊人!6.36MB的import文件夹压缩后只有964KB!现在前端有操作zip的库可以用,所以就想把import目录压缩后再用。
(排版很乱,大家忍着点~ )
6.36MB的import文件夹压缩后只有964KB!

但是后来又发现,加载一个场景并不需要import里面的所有json文件。目前项目构建后的import里面有90几个文件,一个场景只用了大约26个文件。所以想能不能以场景为单位压缩import目录,一个场景打一个zip包(我们的项目使用时一次只用一个场景)。要解决这个问题,就需要研究构建后的setting.js文件。之前在论坛里面问过有没有人能向大家解释下setting.js文件的处理逻辑,但是没人解释,看来得自己研究了。

同时为了更好地模拟实际情况再新建一个空场景,名称为Test

这是本次测试的示例项目(这是Creator自带的TS示例项目),以这个项目为模板讲解构建后的setting.js 文件
Load.zip (64.1 KB)

项目打开截图:

这是web平台构建后的文件夹,本次讲解的是这个目录里面的setting.js文件
web-mobile.zip (464.6 KB)

这是构建参数截图(直接使用正式版,只选择内联所有SpriteFrame):

  1. 先来看一下构建后的setting.js文件:

window._CCSettings = {
platform: “web-mobile”,
groupList: [“default”],
collisionMatrix: [[true]],
rawAssets: {
assets: {
“0”: [“Prefab/root.prefab”,
0]
}
},
assetTypes: [“cc.Prefab”],
launchScene: “db://assets/Scene/helloworld.fire”,
scenes: [{
url: “db://assets/Scene/helloworld.fire”,
uuid: 1
},
{
url: “db://assets/Scene/Test.fire”,
uuid: “16nEH41pZDmr84oqQYyUG6”
}],
packedAssets: {
“01acf5b45”: [2,
“41D7kWhyFGY7q4NDlzkazn”,
0],
“05a04532b”: [1,
2],
“0cfd22b7a”: [“6aoKpq6+5BVaCIpoemqt7E”,
“a8Anh32NZGRZegUtSgEj26”]
},
md5AssetsMap: {},
orientation: “”,
subpackages: {},
uuids: [“dfjxSz6kJAyLAOXioGjgk3”,
“2dL3kvpAxJu6GJ7RdqJG5J”,
“31vIlawANFZqnzLlSuHBfc”]
};

1.1 setting.js中重要的属性介绍如下:
(1)groupList 是分组表,collisionMatrix 是碰撞表
(2)rawAssets 字面意思是生资源、未加工过的资源,一般是图片、声音、预制、二进制文件;rawAssets下assets字段的各个属性都是数字类型的文本,代表的是setting.js文件最后的uuids数组的索引,加载的时候main.js会把这个数字替换为具体的uuid;比如这里assets下的属性"0"表示的是uuids里面的“dfjxSz6kJAyLAOXioGjgk3”。想查看这个uuid的具体内容,可以在Creaor里面打开开发者工具,然后把这个uuid解压为正常的uuid,再在项目的资源库里面搜索,就能找到这个uuid对应的资源。

这是这个uuid对应文件的截图:

可以看到这个文件是项目里面的“resources/Prefab/root.prefab”文件。

assets属性的值是项目resources 文件夹里面文件路径和资源类型;资源类型用数字标记,这个数字标记是下面的assetTypes数组的索引。比如这里的0代表下面assetTypes里的cc.Prefab。

(3) assetTypes 是资源类型数组,比如预制、音效、文本、JSON、二进制等等。这个数组是根据当前项目resources目录下存在的资源类型生成的,每一次生成的数组顺序可能是不一样的。公司项目的assetTypes 数组是这样的:

(4)jsList :导入的js插件列表,每个值是js插件的路径;当前项目没有导入js插件,所以没有这个字段。公司项目的jsList是这样的:

(5)launchScene:启动场景的路径

(6) scenes:当前项目的所有场景信息列表;这个列表里面的每个对象存储了场景的路径和场景的uuid索引,这个索引和其他地方的uuid索引一样,都是下面uuids列表的下标。找到uuid然后解压为未压缩的uuid,就能在项目的资源库里面找到这个场景的json文件了,如下图所示:

(7)packedAssets:打包的资源;Creator 会把一些json文件合并到一个json里面,能减少网络请求,提高效率。这个属性存储的就是打包信息。packedAssets下的字段名称是josn文件名称,可以在构建目录的import文件夹里面找到。packedAssets下的字段的值保存了这个json文件包含的其他json文件的uuid。同理,如果这里的uuid是数字类型,那么可以在uuids列表里面用这个数字做下标找到具体的uuid值。如果这里的uuid不是数字,那么这个json文件保存的一般是多个图片的贴图属性,比如这里的:

“0cfd22b7a”: [“6aoKpq6+5BVaCIpoemqt7E”, “a8Anh32NZGRZegUtSgEj26”]

在构建目录里面搜索“0cfd22b7a”,打开后可以看到这两个uuid对应图片的贴图属性,两张图片的属性是用“|”分割开的,截图如下:

解压uuid “6aoKpq6+5BVaCIpoemqt7E”,可以找到这张图片,截图如下:

packedAssets下字段的生成规则暂时还不知道,谁要知道说一下就好了。

(8)md5AssetsMap:如果构建时选中了“MD5缓存”和“合并初始场景依赖的所有JSON文件”选项,这个对象下会有值。这个对象存储的是构建后每个文件的名称信息。他的子对象表示文件夹,目前只有import(本文类文件,后缀都是json,比如动画anim、场景fire文件和txt文件都会转为json格式存在这里)和"raw-assets"(二进制类(生的)文件,比如图片和音频)。子对象数组中,第0个值和偶数下标上的值表示原始文件名称,奇数下标上的值表示文件的md5后缀,把这两个值合起来,就能找到对应的文件。如果下标上的值为数字类型,则需把这个数字作为下标,在setting.js的uuids数组中找到具体的uuid,然后解压uuid,解压后的uuid才是文件名称。比如import中的 : 2,“0322e”

md5AssetsMap: {
import: [“030b040d6”,
“b3451”,
“098273a93”,
“07817”,
2,
“0322e”,
4,
“c645d”],
“raw-assets”: [3,
“55ea4”,
4,
“e5136”]
},

uuids中下标为2的uuid是"16nEH41pZDmr84oqQYyUG6",解压:

Editor.Utils.UuidUtils.decompressUuid(“16nEH41pZDmr84oqQYyUG6”)
“169c41f8-d696-439a-bf38-a2a418c941ba”

然后打开这个文件,可以看到是一个场景文件,也验证了之前的说明:

setting.js文件后面有个立即运行函数,否则的就是把md5AssetsMap子对象里面的数字下标还原为具体的uuid,如下:

(function (e) {
var t = e.uuids,
i = e.md5AssetsMap; for (var s in i) for (var n = i[s],
r = 0; r < n.length; r += 2)“number” == typeof n[r] && (n[r] = t[n[r]])
})(window._CCSettings)

今天发现打包后文件的md5后缀是用gulp-rev-all插件生成的


~~~~~~20190614 更新~~~~~~
忙了一段时间,终于搞明白了md5后缀的文件的使用方式

**为了更好地模拟实际生产环境,构建时选中“MD5缓存”和“合并初始场景依赖的所有JSON文件”选项,截图如下:**
<img src="/uploads/default/original/3X/9/1/9151014f55531d827008d7a0ecea54e27f45d210.png" width="446" height="500">


现在构建之后setting.js文件是这样的(为了方便,处理过):

 >    window._CCSettings = {
>         platform: "web-mobile",
>         groupList: ["default"],
>         collisionMatrix: [[true]],
>         rawAssets: {
>             assets: {
>                 "1": ["Prefab/root.prefab",
>                     0]
>             }
>         },
>         assetTypes: ["cc.Prefab"],
>         launchScene: "db://assets/Scene/helloworld.fire",
>         scenes: [{
>             url: "db://assets/Scene/helloworld.fire",
>             uuid: 0
>         },
>         {
>             url: "db://assets/Scene/Test.fire",
>             uuid: 2
>         }],
>         packedAssets: {
>             "030b040d6": [0,
>                 "31vIlawANFZqnzLlSuHBfc",
>                 3],
>             "098273a93": ["41D7kWhyFGY7q4NDlzkazn",
>                 1]
>         },
>         md5AssetsMap: {
>             import: ["030b040d6",
>                 "b3451",
>                 "098273a93",
>                 "07817",
>                 2,
>                 "0322e",
>                 4,
>                 "c645d"],
>             "raw-assets": [3,
>                 "55ea4",
>                 4,
>                 "e5136"]
>         },
>         orientation: "",
>         subpackages: {},
>         uuids: ["2dL3kvpAxJu6GJ7RdqJG5J",
>             "dfjxSz6kJAyLAOXioGjgk3",
>             "16nEH41pZDmr84oqQYyUG6",
>             "6aoKpq6+5BVaCIpoemqt7E",
>             "a8Anh32NZGRZegUtSgEj26"]
>     }; (function (e) {
>         var t = e.uuids,
>         i = e.md5AssetsMap; for (var s in i) for (var n = i[s],
>             r = 0; r < n.length; r += 2)"number" == typeof n[r] && (n[r] = t[n[r]])
>     })(window._CCSettings);


可以发现,构建时选择“MD5缓存”和“合并初始场景依赖的所有JSON文件”后,seting.js文件里面packedAssets数量明显减少了,同时md5AssetsMap 里面也有值了。



**再来分析下构建时选择“合并初始场景依赖的所有JSON文件”后setting.js文件的变化。**

选中“合并初始场景依赖的所有JSON文件”后,packedAssets的属性数量由3个变为2个。根据这个选项的名称可以知道,它是把初始场景依赖的所有JSON文件合并了。示例项目的初始场景是helloworld,uuid索引是1,根据上面的分析,这个场景文件本身保存在05a04532b.json 文件里面,打开后如下:
<img src="/uploads/default/original/3X/b/7/b76604e05cf519ba7584dbb3f0affa842f055cf4.png" width="452" height="500">

可以看到这个json文件存储了helloworld场景和名称为HelloWorld的贴图,贴图的id为6aoKpq6+5BVaCIpoemqt7E,把贴图id转为uuid,可以在构建目录查看这张图片:

> 解压uuid:
> Editor.Utils.UuidUtils.decompressUuid("6aoKpq6+5BVaCIpoemqt7E")
> "6aa0aa6a-ebee-4155-a088-a687a6aadec4"


<img src="/uploads/default/original/3X/4/f/4f4cb6da07f7ae23c6ab1a39b6daf735f2299312.png" width="646" height="500">


这张图片就是项目里面的HelloWorld图片,验证一下:

<img src="/uploads/default/original/3X/0/1/01093e301557fadd8b5b49f3636a798ad9bf4824.png" width="690" height="347">

另外 packedAssets的"05a04532b"里面还有一个uuid索引为2("31vIlawANFZqnzLlSuHBfc")的资源,但是解压这个uuid后却找不到对应的文件,尝试在构建目录搜索时,发现这个uuid就是图片HelloWorld使用时的引用id,如下图所示:
<img src="/uploads/default/original/3X/2/b/2b854e95276043dcd38cfca9ff33c7a71f225254.png" width="690" height="441">

场景helloworld中的使用情况:
<img src="/uploads/default/original/3X/4/6/464da85c759cb192c50887e64e9cfdab2767b499.png" width="690" height="443">

同时这个图片还被预制root使用了,所以也出现在了01acf5b45 文件中。

 packedAssets的"0cfd22b7a"里面也用到了HelloWorld("6aoKpq6+5BVaCIpoemqt7E")图片,打开05a04532b.json文件后,发现存储的是两张图片的属性信息:

另一张图片uuid是a8Anh32NZGRZegUtSgEj26,解压后是"a8027877-d8d6-4645-97a0-52d4a0123dba",打开这个图片,是:
<img src="/uploads/default/original/3X/4/9/49fa4d73641f510748dcb7be7a30e5c38900d481.png" width="690" height="362">
(一个单色的点)

搜索一下这张图片的引用情况,可以看到这是场景里面使用的单色精灵:
<img src="/uploads/default/original/3X/5/a/5a52b630af1fd2f5ad2f5a8d71e326ff4969b29a.png" width="690" height="385">

到这里,我们可以先得出一个结论:packedAssets存储的是这个json里面保存的资源情况,比如这里的05a04532b 表示05a04532b.json文件存储了helloworld场景和HelloWorld贴图的信息


有了上面的知识后,再看选择了“MD5缓存”和“合并初始场景依赖的所有JSON文件”构建后的setting.js文件的packedAssets:
<img src="/uploads/default/original/3X/8/3/83e5428b7943c08b98b20d97c89593f47b211fc3.png" width="690" height="220">
打开以030b040d6开头的json文件:
<img src="/uploads/default/original/3X/f/7/f7cc0891e9276279f75b651ade54f7c6d4258f1c.png" width="392" height="500">
可以看到helloworld场景依赖的资源都被合并到这个文件里面了。

再看一下加载情况:
开了合并选项时:
<img src="/uploads/default/original/3X/9/6/96a7e4d2a766bd9b8ccc4eb77f27b80ac8de1faf.png" width="690" height="89">
没开时:
<img src="/uploads/default/original/3X/7/7/7748a722369f6e7669ea72d6e501e476c0def7f2.png" width="690" height="117">

和我们的结论一致。


到这里setting.js文件就解释完了,也有了加载单个场景的方法:把这个场景本省以及这个场景依赖的资源找到,打包为zip压缩包,自定义load下载器,当加载的资源名称为场景相关资源时,直接从解压好的zip包里面返回数据即可。


#### 20190722 更新一下
>settings.js里面md5AssetsMap所有属性数组长度之和除以2,就是构建文件夹res目录里面文件的数量。
用我们公司的的项目构建目录验证一下:
<img src="/uploads/default/original/3X/f/1/f1788ae51a1a9ed7eee25820fd0ed20fd1203b2b.png" width="690" height="360">

>另外,构建目录的“res/import”目录存储的都是json数据,具体信息由 md5AssetsMap 的import 属性指定,md5AssetsMap 的两个 属性都是数组,里面的值如果是数字,则表示uudis中的索引;
md5AssetsMap 的属性数组中,偶数索引(但是包括零)表示文件名称点“.”之前的部分,一般为9位或者22位字符串,前两位是上级文件夹的名称;奇数索引表示文件名称“.”号之后的部分,字符长度都是5位,这是文件的md5后缀,没猜错的话,是用npm的“gulp-rev-all”模块生成的,属于构建的最后一步。两者合起来就是文件名称,import里面都是json格式,raw-assets里面大都是png、mp3、bin 等格式。


这个帖子先占个坑,后面慢慢写。

Creator 版本2.1.0
18赞

有操作过程吗?

还没写完,这个坑很大,我慢慢补

mark 一记 这是为了提高 加载速度么

先跟踪一下,再慢慢看。

问一下楼主 这个解压缩uuid的命令 是在 cocoscretor 编辑器的 后台调试页面吗? http://localhost:端口号??

你想压缩的json文件,不是资源的属性信息吗,浏览器回先请求下来json和对应的资源解析json去设置资源的属性,你不修改引擎的解析方式,怎么实现?,不是有直接合并这些json的内容为一个或少量json的方式吗

这个帖子里面记录了操作过程,但是排版不好,多读几遍,跟着做下就明白了

是的,为了调高加载速度,否则josn小文件太多,导致网络请求很多。到时候把import文件夹压缩,放到cdn上,速度会好很多

不是,是在开发者工具里面,多看看Creaotr文档就明白了,这样打开:

合并是一方面,我想把import里面的json文件分场景压缩,再放到cdn上,速度快很多。解析方式会按需修改。另外你的回复是不是有语病,看着难受

坐等后续文章

最近忙别了,回头再搞

mark一下

Mark

真有耐心,佩服!!期待你的成果。

mark

http gzip了解一下

关于最终文件名映射反推非常复杂,creator有个把资源路径转成序列化名的方法,但没有反推方法,

官方之前有个插件BuildTextures,就是构建完成后从creator发布数据db里可以查询所有的资源文件名映射,推荐从那个入手。
https://forum.cocos.com/t/topic/76554

mark

拜谢楼主,满满的干货,坐等更新。项目七月底要上线了,同样遇到了加载速度慢的问题,学习了。