天天看点

Egret资源管理解决方案

转载于:https://www.cnblogs.com/gamedaybyday/p/6079694.html

关于egret开发H5页游,资源管理和加载的一点看法。

一 多json文件管理

二 资源归类和命名

三 资源预加载、分步加载、偷载

四 资源文件group分组

五 ResUtils,多json文件管理类

六 ResUtils,资源组加载管理类

一 多json文件管理

当多人协作时,添加资源时常因为资源文件修改而导致svn冲突。

根据各人不同负责的模块,将资源文件划分。

原来的

default.res.json           

复制

可以修改为

login.res.json
hall.res.json
game.res.json
sound.res.json
...           

复制

二 资源归类和命名

asset文件夹下,分类存放图片。根据项目可自行划分。

Egret资源管理解决方案

为了防止多个文件中资源命名冲突,软件只有检测单文件中命名冲突,没有自动检测多文件命名冲突的功能。

所以可以加前缀解决。

login_loginbtn
login_logo

hall_roombg
hall_setbtn

game_bg
game_option
....           

复制

对于公用的图片,尤其是login、hall、game中通用的按钮和背景,可以单独放在common资源组中,以备复用。

一来防止图片多次加载,导致发包体积过大。二来修改按钮图片时,只需修改一处即可。

com_btn0
com_btn1
com_box0
com_box1
com_panelbg
...           

复制

三 资源预加载、实时加载、偷载

1. 黑屏  

在进入preload预加载界面时,此时会有短暂的黑屏。可将html背景色设置为白色或其他颜色,感觉比黑屏要好一些。

2. 预加载

打开场景。 从preload进入login场景时,预先加载login界面的资源,给出加载loading界面,加载完成后再进入login。

Egret资源管理解决方案

3. 实时加载

预加载只加载用户一进入场景时所见资源,其他该场景资源,比如弹框资源等,在使用时再实时加载。这样可以大大减少用户进入场景等待时间。

在打开弹框时,给出loading动画,加载完后再显示弹框。

Egret资源管理解决方案
Egret资源管理解决方案

弹框除了资源,还有http请求显示的数据,这个请求也需要时间等待,未返回数据前,界面数据为空,或者显示之前请求的数据,等加载完成再显示更新。

如下图,当http请求无返回数据时,界面是空的,或者是之前请求的数据。

Egret资源管理解决方案

当http请求返回数据时,再更新该弹框。

Egret资源管理解决方案

3. 偷载

进入某场景后,用户可能不会马上进行某些操作。进入场景后即刻加载该场景所用资源。不用显示loading画面,在用户不知的情况完成加载。

四 资源文件group分组

资源文件可按照场景、弹框、通用来分组。

场景必须资源:preload、login、hall、game

大厅中弹框资源:option、rank、mission、skill、roleInfo

声音资源:sound

通用资源:common

根据项目可自行细分。

资源组划分的目的,就是将资源分类管理,方便在加载时使用。

在进入login场景时,只加载login资源组。打开设置弹框时,只加载option资源组。

五 ResUtils,多json文件管理类

六、七代码部分参考了Egret论坛某人的代码,略微修改了一下。首先感谢这位仁兄分享自己的代码,其次我忘了他叫啥了- -! 。。。

ResUtils.ts

/**
 * 资源加载工具类,
 * 支持多个resource.json文件加载
 */
class ResUtils  {
    private static instance:ResUtils;
    private _configs: Array<any>;
    private _onConfigComplete: Function;
    private _onConfigCompleteTarget: any;

    public static getInstance():ResUtils{
        if(this.instance == null){
            this.instance = new ResUtils();
        }
        return this.instance;
    }
    
    /**
     * 构造函数
     */
    public constructor() {
        this._configs = new Array<any>();
    }

    /**
     * 添加一个配置文件
     * @param jsonPath resource.json路径
     * @param filePath 访问资源路径
     */
    public addConfig(jsonPath: string,filePath: string): void {
        this._configs.push([jsonPath,filePath]);
    }

    /**
     * 开始加载配置文件
     * @param $onConfigComplete 加载完成执行函数
     * @param $onConfigCompleteTarget 加载完成执行函数所属对象
     */
    public loadConfig($onConfigComplete: Function,$onConfigCompleteTarget: any): void {
        this._onConfigComplete = $onConfigComplete;
        this._onConfigCompleteTarget = $onConfigCompleteTarget;
        this.loadNextConfig();
    }

    /**
     * 加载
     */
    private loadNextConfig(): void {
        //加载完成
        if(this._configs.length == 0) {
            this._onConfigComplete.call(this._onConfigCompleteTarget);
            this._onConfigComplete = null;
            this._onConfigCompleteTarget = null;
            return;
        }

        var arr: any = this._configs.shift();
        RES.addEventListener(RES.ResourceEvent.CONFIG_COMPLETE,this.onConfigCompleteHandle,this);
        RES.loadConfig(arr[0],arr[1]);
    }

    /**
     * 加载完成
     * @param event
     */
    private onConfigCompleteHandle(event: RES.ResourceEvent): void {
        RES.removeEventListener(RES.ResourceEvent.CONFIG_COMPLETE,this.onConfigCompleteHandle,this);
        this.loadNextConfig();
    }
}           

复制

//加载多个资源文件
ResUtils.getInstance().addConfig("resource/test.json","resource/");
ResUtils.getInstance().addConfig("resource/test2.json","resource/");
ResUtils.getInstance().loadConfig(this.onConfigComplete, this);           

复制

六 ResUtils,资源组加载管理类

ResUtils.ts

/**
 * 资源加载
 * 支持单个或多个资源组加载
 */
class ResUtils extends BaseClass {
    /**保存资源组名*/
    private groups: any;

    /**
     * 构造函数
     */
    public constructor() {
        super();
        this.groups = {};

        RES.addEventListener(RES.ResourceEvent.GROUP_COMPLETE,this.onResourceLoadComplete,this);
        RES.addEventListener(RES.ResourceEvent.GROUP_PROGRESS,this.onResourceLoadProgress,this);
        RES.addEventListener(RES.ResourceEvent.GROUP_LOAD_ERROR,this.onResourceLoadError,this);
    }
    
    /**
     * 加载资源组,静默加载(无回调函数)
     * @group 资源组(支持字符串和数组)
     */ 
    public loadGroupQuiet(group){
        var groupName:string = this.combGroupName(group);
        RES.loadGroup(groupName);
    }
    
    /**
     * 加载资源组,带加载完成回调
     * @group 资源组(支持字符串和数组)
     * @onComplete 加载完成回调
     * @thisObject 回调执行对象
     * @priority 优先级
     */ 
    public loadGroup(group, onComplete:Function, thisObject:any, priority:number = 1){
        var groupName:string = this.combGroupName(group);
        this.groups[groupName] = [onComplete,null,thisObject];
        RES.loadGroup(groupName);
    }
    
    
    /**
     * 加载资源组,带加载进度
     * @group 资源组(支持字符串和数组)
     * @onComplete 加载完成回调
     * @onProgress 加载进度回调
     * @thisObject 回调执行对象
     */
    public loadGroupWithPro(group ,onComplete: Function,onProgress: Function,thisObject: any): void {
        var groupName:string = this.combGroupName(group);
        this.groups[groupName] = [onComplete,onProgress,thisObject];
        RES.loadGroup(groupName);
    }
    
    
    /**
     * 组合资源组名。单个资源组直接返回。多个资源组则重新命名。
     * @group 新资源组名
     */ 
    private combGroupName(group){
        if(typeof(group) == "string"){
            return group;
        }else{
            var len = group.length;
            var groupName:string = "";
            for(var i=0;i<len;i++){
                groupName += group[i];
            }
            RES.createGroup(groupName,group,false); //是否覆盖已经存在的同名资源组,默认 false
            return groupName;
        }
    }

    /**
     * 资源组加载完成
     */
    private onResourceLoadComplete(event: RES.ResourceEvent): void {
        var groupName: string = event.groupName;
        console.log("资源组加载完成:" + groupName);
        if(this.groups[groupName]) {
            var loadComplete: Function = this.groups[groupName][0];
            var loadCompleteTarget: any = this.groups[groupName][2];
            if(loadComplete != null) {
                loadComplete.call(loadCompleteTarget);
            }

            this.groups[groupName] = null;
            delete this.groups[groupName];
        }
    }

    /**
     * 资源组加载进度
     */
    private onResourceLoadProgress(event: RES.ResourceEvent): void {
        var groupName: string = event.groupName;
        if(this.groups[groupName]) {
            var loadProgress: Function = this.groups[groupName][1];
            var loadProgressTarget: any = this.groups[groupName][2];
            if(loadProgress != null) {
                loadProgress.call(loadProgressTarget,event);
            }
        }
    }

    /**
     * 资源组加载失败
     */
    private onResourceLoadError(event: RES.ResourceEvent): void {
        console.log(event.groupName + "资源组有资源加载失败");
        this.onResourceLoadComplete(event);
    }
}           

复制

测试加载

var res:ResUtils = ResUtils.getInstance();
//res.loadGroupQuiet("login");
//res.loadGroup("login", ()=>{ console.log("login load complete")}, this);
//res.loadGroupWithPro("login", 
//    ()=>{console.log("login load complete")}, 
//    (e:RES.ResourceEvent)=>{console.log("login progress",e.itemsLoaded,e.itemsTotal)},this);
      
res.loadGroupQuiet(["preload","login"]);           

复制