3D游戏3D素材资源zip压缩解决方案
近期使用Laya开发了个3D游戏,遇到了这样的问题,3D素材资源加载很慢。前端工程师都知道,影响网络加载速度的因素除了下载文件体积之外还有一个就是http请求过多。
3D资源恰恰是一大堆零散的小文件,如果是2d项目呢,可以通过把图片合集的方式减少图片请求,但3d包含多种不同格式的文件,不能合成。那怎么办? 想到了zip压缩包的方式,把3d素材文件打包成1个或多个zip包。
zip包的解压在纯h5项目需要借助第三方类库来实现,并不方便。可喜的是微信小游戏基础库提供了解压api,这样大大简化了开发难度和保证了兼容性、稳定性。
思路很简单:
判断游戏本地临时文件夹是否存着3d素材文件,如果有,直接返回,如果没有,先进行下载,待下载完解压成功后返回。需要做好兼容,zip下载或解压出现问题时需要加载零散的原始文件。
核心伪代码:
/**
*
* @param url 压缩包zip路径
* @param callBack 回调函数,失败返回-1
* @param checkurl 本地文件路径,判断是否存在
*/
public static downWXFile(url:string, callBack:Function, checkurl:string){
let log = false;
log && console.log("wx下载", url, checkurl);
if(checkurl){ //如果本地有这个文件,不下载直接返回
let fs = window["wx"].getFileSystemManager();
try {
fs.accessSync(checkurl); //不报try catch 表示有这个文件
log && console.log("有文件,直接返回:", checkurl)
return callBack && callBack();
}catch (e) {
log && console.log(e);
}
}
let obj:any = {
url: url,
success: (res)=> {
// 只要服务器有响应数据,就会把响应内容写入文件并进入 success 回调,业务需要自行判断是否下载到了想要的内容
if (res.statusCode === 200) {
const WX_ROOT = ConfigDC.zip3DRoot; //wx["env"].USER_DATA_PATH + "/res";
// console.log(res.tempFilePath, WX_ROOT);
let fs = window["wx"].getFileSystemManager();
let arg:any = {
zipFilePath: res.tempFilePath,
targetPath: WX_ROOT,
success: (ras)=>{
log && console.log("wx解压成功!", WX_ROOT, ras);
callBack && callBack();
},
fail: (ras)=>{
log && console.log("upzip-fail", ras)
jsErrorReport("upzip-fail--" + window["system_data"].version + "--" + res.errMsg); //记录错误日志
callBack && callBack(-1);
}
};
fs.unzip(arg);//这里直接解压,无需判断文件夹,在版本更新的时候需要调用clearTempCache 清空文件夹
}
},
fail: (res)=>{
log && console.log("down-fail", res)
jsErrorReport("down-fail--" + window["system_data"].version + "--" + res.errMsg); //记录错误日志
callBack && callBack(-1);
}
}
wx.downloadFile(obj)
}
private loadFile(){
if(zip3DFile){ //判断是否启用zip资源加载
this.listNum++;
var url = ConfigDC.zip3DRoot + "/3d/car.ls";
AppFuncDreamCar.downWXFile( ConfigDC.localres3D + "3d.zip", (result:number)=>{
let arr:any = [url];
if(result == -1)
arr = [{url:ConfigDC.localres3D + "3d/car.ls"}]; //失败,加载网络路径
Laya.loader.create(arr, Laya.Handler.create(this, ()=>{
this.listNum--;
this.onLoaded();
}));
}, url);
}
else{// 不启用zip加载,直接请求 主ls文件
loadlist.push({url:ConfigDC.localres3D + "3d/car.ls"});
}
Laya.loader.create(loadlist, Laya.Handler.create(this,this.onLoaded));
}
需要特别注意的是:该功能在开发者工具里面测试是失败的,需要到真机里面测试,才成功。