FairyGUI-egret 优化ui资源加载
背景:egret重度游戏项目,ui资源都比较大,加载较慢,翻翻加载ui的源码看一下有没有优化空间:
https://github.com/fairygui/FairyGUI-egret/blob/master/source/src/UIPackage.ts
public static async loadPackage(resKey: string): Promise<UIPackage> {return new Promise<UIPackage>(async resolve => {let pkg: UIPackage = UIPackage._instById[resKey];if (pkg) {resolve(pkg);return;}const asset = await RES.getResAsync(getAssetResKey(resKey, "fui"));pkg = new UIPackage();pkg._resKey = resKey;pkg.loadPackage(new ByteBuffer(asset));let cnt: number = pkg._items.length;let tasks = [];for (var i: number = 0; i < cnt; i++) {var pi: PackageItem = pkg._items[i];if (pi.type == PackageItemType.Atlas || pi.type == PackageItemType.Sound) {tasks.push(RES.getResAsync(pi.file));}}if (tasks.length > 0)await Promise.all(tasks);UIPackage._instById[pkg.id] = pkg;UIPackage._instByName[pkg.name] = pkg;UIPackage._instById[pkg._resKey] = pkg;resolve(pkg);});}
可以看到代码里是先加载 .fui 的配置资源,等到它加载完成后,从其中解析出需要的 atlas\sound 资源,然后等待所有的资源加载,ui加载完成。而egret在运行会通过 assetsManager 加载全量资源的映射表,我们可以在此时建 收集每个fgui包的全部资源(即 .fgui配置 和 atlas\sound 资源),这样在loadPackage 时直接并行加载单个ui包的全部资源,理论上单个包的加载速度可以提升近一倍。
具体代码修改如下:
egret - assetsmanager:
src/extension/assetsmanager/src/core/FileSystem.ts
export interface FileSystem {...+++++++++++++++++++++>>>>>> line 44collectFguiPkgAtlasAndSound(pkg:string, name:string):void;getFguiPkgAtlasAndSounds(pkg:string): string[];<<<<<<+++++++++++++++++++++
}
src/extension/assetsmanager/src/core/ResourceConfig.ts
export class ResourceConfig {...+++++++++++++++++++++>>>>>> line 265public getFguiPkgItems(pkgName:string): string[] {return config.config.fileSystem.getFguiPkgAtlasAndSounds(pkgName);}
<<<<<<+++++++++++++++++++++ ...
}
src/extension/assetsmanager/src/processor/Processor.ts
if (!fileSystem) {fileSystem = {...+++++++++++++++++++++>>>>>> line 639},fguiPkgAtlasAndSound: {},collectFguiPkgAtlasAndSound:(pkgName:string, name:string)=>{let temp:string[] = fguiPkgAtlasAndSound[pkgName];if (!temp) {temp = [];fguiPkgAtlasAndSound[pkgName] = temp;}temp.push(name);},getFguiPkgAtlasAndSounds:(pkgName:string)=>{return fguiPkgAtlasAndSound[pkgName];
<<<<<<+++++++++++++++++++++...}+++++++++++++++++++++>>>>>> line 667let fguiPkgAtlasAndSound: {[index:string]:string[]} = fileSystem['fguiPkgAtlasAndSound'];
<<<<<<+++++++++++++++++++++for (let resource of data.resources) {...
+++++++++++++++++++++>>>>>> line 678//fgui 资源if (resource.url.substring(0,10) == "assets/ui/") {let subfix = resource.url.substring(10+resource.name.length)switch(subfix) {case ".fui":fileSystem.collectFguiPkgAtlasAndSound(resource.name, resource.name);break;case ".mp3":let idx_ = resource.name.lastIndexOf('_');fileSystem.collectFguiPkgAtlasAndSound(resource.name.substring(0,idx_), resource.name);breakcase ".jpg":case ".png":let idx_atlas = resource.name.lastIndexOf('_atlas');fileSystem.collectFguiPkgAtlasAndSound(resource.name.substring(0,idx_atlas), resource.name);break;default:console.warn("unparsered fgui resource :" + resource.url);}}
<<<<<<+++++++++++++++++++++}
+++++++++++++++++++++>>>>>> line 702for(let key in fguiPkgAtlasAndSound) {let temp:string[] = fguiPkgAtlasAndSound[key];temp.sort(); //排序后第一个应为 .fui文件}
<<<<<<+++++++++++++++++++++
src/extension/assetsmanager/src/shim/Resource.ts
module RES {...
+++++++++++++++++++++>>>>>> line 320export function getFguiPkgItems(pkgName: string): string[] {return instance.getFguiPkgItems(pkgName);}<<<<<<+++++++++++++++++++++...export class ResourceConfig {...+++++++++++++++++++++>>>>>> line 829/*** 获取配置文件中 fugi 包的资源名合集* @method RES.getFguiPkgItems* @param pkgName {string} 包名* @returns {string[]}*/@checkNullpublic getFguiPkgItems(pkgName:string): string[] {return config.getFguiPkgItems(pkgName);}
<<<<<<+++++++++++++++++++++...}
FairyGUI
src/UIPackage.ts
public static async loadPackage(resKey: string): Promise<UIPackage> {...let keys = RES.getFguiPkgItems(resKey);for(let key of keys) {tasks.push(RES.getResAsync(key))}let assets = await Promise.all(tasks);pkg = new UIPackage();pkg._resKey = resKey;pkg.loadPackage(new ByteBuffer(assets[0]));...
}