这几天在优化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):
- 先来看一下构建后的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