-前言-
小游戏之所以称为小游戏,首先它的资源量就被限制在一个很小的区间,在微信及QQ小游戏上包大小有4M要求,即使使用分包也只能扩展到8M的大小,这与我们一般的APP游戏的资源两级是不能比的。不过随着小游戏的发展,我们可以将资源放到CDN,通过远程拉取的方式加载资源,这与我们以前的页游相当。接下来就具体讨论下小游戏的加载优化有哪些及资源分配的细节。
-正文-
我们平时制作小游戏一般都不会使用微信开发者工具开发小游戏,这之后所有代码出现都是关于Laya的代码,不过思路基本相似。
声音资源
声音资源一般是偏大的资源类型,一般我们将这部分资源直接放到CDN上,需要使用的时候加载,我们在入口场景初始化前是不会对其加载的。
图集资源
图集分类
图集资源资源是我们最需要好好管理的资源类型,因为随着项目的改进,会不断增删资源,要适时的删除不需要的资源。在资源分配的时候,首场景的资源放到一个图集之中。之后按功能及逻辑紧密性分配不同图集之中,分配资源属于哪个图集之中需要注意另一个问题。一个图集中的所有文件碎图都隶属于同一个Texture纹理对象,如果同一功能面板内的资源来自多个不同图集,会导致多次切换纹理及增加drallcall次数,我们需要在图集分类及优化渲染之间做好平衡。
一般项目图集资源分类包括
- 加载界面资源
- 首次场景资源
- 其余功能资源
图集过大的一些问题
当我们实在一个文件夹中的图片太多并且也无法拆分时,Laya会自动根据单图集最大尺寸生成多张图片及一个配置文件。这里有一个问题就是一般我们的加载都是可以并行加载,根据不同平台,并行数量不同,但是来源于同一个配置文件的图集图片是不能并行加载的,是完全的串行加载。这会使得加载非常缓慢。下面是对于图集文件加载完成的逻辑,当我们.atlas文件加载完成后会加载对应图片文件,这部分是加载一个处理一个图片并生成纹理。因此我们应该尽量避免单个图集大于我们所定义的最大图集大小。解决方案可以修改这部分源代码或者修改最大图集大小,不过都不是最好的方式,管理好我们的图集才是解决之道。
//当图集文件加载完成后加载对应Image逻辑
else if (type==="atlas"){
if (!data.url && !data._setContext){
if (!this._data){
this._data=data;
//省略部分代码
toloadPics.reverse();
data.toLoads=toloadPics;
data.pics=[];
}
this.event(/*laya.events.Event.PROGRESS*/"progress",0.3+1 / toloadPics.length *0.6);
return this._loadImage(toloadPics.pop());
}else {
this._data.pics.push(data);
if (this._data.toLoads.length > 0){
this.event(/*laya.events.Event.PROGRESS*/"progress",0.3+1 / this._data.toLoads.length *0.6);
return this._loadImage(this._data.toLoads.pop());
};
//省略解析图片代码
delete this._data.pics;
this.complete(this._data);
}
}
另外当我们一个图集过大的时候,解析时间也会随之增大,所以合理控制图集大小是非常必要的。这里需要说明的是,图片加载完成后并不是这个Load结束的时候,正真结束的时候是在我们解析图集完成之后。
图集压缩
图集是一个相对较大的资源类型,在发布的时候我们都需要对图集进行压缩,Laya压缩使用的pngquant(png),guetzli(jpg),我们也可以使用别的压缩软件及开源程序。一般压缩都是将png32数据有损压缩到png8,压缩也要适当,不然也会出现失真问题。
配置文件
小游戏配置文件一般使用json文件,一个是Web环境天生很好支持json,另一个json相对于其他数据文件大小也更小。不过在我们生成配置文件的时候也应该尽量简洁,尽量避免json写死数据,配置文件应该是公式参数而不是公式结果。另外当配置文件过多的时候也应该达到资源整合,避免过高的Http请求。配置文件也需要进行压缩,不过没有很好的压缩方式,一般都是通过JSON接口转成JSON对象再转json字符串就完成了压缩。
加载优化
前面说的这么多都是关于资源分配的东西,都是加载之前的东西。关于加载优化一般都是按需加载。小游戏加载分两种加载情况:
- 完全放到小游戏平台CDN,进入小游戏由平台API拉取我们所有资源到小游戏的执行域
- 除了代码所有资源放到开发者的自己的CDN中。
上面两种方式都各有利弊。首先如果我们把所有资源放到平台哪里,我们很难在资源加载部分做数据分析,因为不了解各个平台是如何加载资源的,我只肯定我们的资源肯定都是放到他们的CDN上的,所以肯定拉取速度也跟节点及自己的网速相关,这是一个不可控的过程。我个人还是推荐将资源放到自己的CDN中,当代码加载完成后,执行到我们的逻辑中,我们就可以监控玩家的加载情况。
加载日志
加载的时候我们需要记录玩家加载进度、加载时间、当前网路状况,在分析数据的时候将网络极差的剔除分析对我们的优化有更好的帮助。
按需加载
我们的游戏框架一定要实现的就是每个功能模块开始执行逻辑之前加载对应要使用的资源对象。我们进入游戏的那个加载阶段也只是加载我们游戏一开始必要的资源,这个资源不一定是完全确定的,可能需要根据玩家不同进度去加载不同资源。
加载中的逻辑代码
资源加载是一个异步的过程,并不会阻塞我的主线程执行,因此当我们加载资源的时候可以初始化我们的数据模块,及任何不需要用到资源的逻辑相关代码。等到资源真正加载好的时候,我们只需要把盖在游戏场景前的画面去掉就无缝连接到我们的正真的游戏场景。