框架的UI
和Panel
都是预设资源,需要动态加载,而引擎只提供了回调方式加载资源的接口,而回调层次多了会造成代码难以理解,所以需要自己封装异步接口。
场景新建一个Label
,内容任意,然后把它拖动到resources
目录下并从场景删除。
新建framework/scripts/manager/ResMgr.ts
,内容如下。
export default class ResMgr {
public static loadRes<T extends cc.Asset>(path: string, type?: typeof cc.Asset) {
return new Promise<T>((resolve, reject) => {
cc.resources.load(path, type, (err: Error, assets: T) => {
if (err) {
reject(err)
return
}
resolve(assets)
})
})
}
}
编辑scripts/Main.ts
脚本,改动后如下。这里只放了修改后的onLoad
函数代码,如果提示找不到ResMgr
,就在顶部输入import ResMgr from "../framework/scripts/manager/ResMgr"
,或者用自己的ide
自动导入。后面修改的代码如果出现类似情况也按照这样的方法处理。
protected async onLoad() {
App.init()
const lblTestPrefab = await ResMgr.loadRes<cc.Prefab>('lblTest')
const lblTest = cc.instantiate(lblTestPrefab)
lblTest.parent = this.node
}
运行程序,看到Label
正确加载了。
这是正确运行的情况,如果把ResMgr.loadRes<cc.Prefab>('lblTest')
修改成ResMgr.loadRes<cc.Prefab>('lblTest2')
加载不存在的资源,会发现程序崩溃了(后续代码逻辑不能正常运行),因为没有处理出现错误的情况。
现在我们做错误处理,代码如下。
protected async onLoad() {
App.init()
try {
const lblTestPrefab = await ResMgr.loadRes<cc.Prefab>('lblTest2')
const lblTest = cc.instantiate(lblTestPrefab)
lblTest.parent = this.node
} catch (error) {
console.error(`ResMgr.loadRes err:${error}`)
}
}
再次运行程序,发现错误已经捕捉到了,但每个地方都try
一下的话代码太啰嗦了,所以把这个错误处理封装一下。
编辑framework/scripts/AppUtil.ts
,添加asyncWrap
函数。
// 异步封装
public static async asyncWrap<T>(promise: Promise<T>): Promise<[T?, any?]> {
try {
return [await promise, null]
} catch (error) {
return [null, error]
}
}
编辑scripts/Main.ts
脚本,改动后如下。
protected async onLoad() {
App.init()
const [lblTestPrefab, err] = await AppUtil.asyncWrap<cc.Prefab>(ResMgr.loadRes('lblTest2'))
if (err) {
console.error(`ResMgr.loadRes lblTest err:${err}`)
return
}
const lblTest = cc.instantiate(lblTestPrefab)
lblTest.parent = this.node
}
这样同时返回了需要加载的资源和错误信息,如果有错误信息,说明资源加载失败,只要处理错误就行,而没错误信息就正常处理。
再次编辑framework/scripts/manager/ResMgr.ts
,封装一些其它常用的加载资源的函数,完整代码如下。
export default class ResMgr {
public static load<T extends cc.Asset>(bundleName: string, path: string) {
if (bundleName) {
return this.loadBundleRes<T>(bundleName, path)
}
return this.loadRes<T>(path)
}
public static loadRemote<T extends cc.Asset>(path: string) {
return new Promise<T>((resolve, reject) => {
cc.assetManager.loadRemote(path, (err: Error, asset: T) => {
if (err) {
reject(err)
return
}
resolve(asset)
})
})
}
public static loadBundle(bundleName: string) {
return new Promise<cc.AssetManager.Bundle>((resolve, reject) => {
const bundle = cc.assetManager.getBundle(bundleName)
if (bundle) {
resolve(bundle)
return
}
cc.assetManager.loadBundle(bundleName, (err: Error, bundle: cc.AssetManager.Bundle) => {
if (err) {
reject(err)
return
}
resolve(bundle)
})
})
}
public static loadBundleRes<T extends cc.Asset>(bundleName: string, path: string, type?: typeof cc.Asset) {
return new Promise<T>((resolve, reject) => {
this.loadBundle(bundleName).
then(bundle => {
bundle.load(path, type, (err: Error, asset: T) => {
if (err) {
reject(err)
return
}
resolve(asset)
})
}).
catch(err => {
reject(err)
})
})
}
public static loadBundleResDir<T extends cc.Asset>(bundleName: string, path: string, type?: typeof cc.Asset) {
return new Promise<T[]>((resolve, reject) => {
this.loadBundle(bundleName).
then(bundle => {
bundle.loadDir(path, type, (err: Error, assets: T[]) => {
if (err) {
reject(err)
return
}
resolve(assets)
})
}).
catch(err => {
reject(err)
})
})
}
public static loadBundleResArray<T extends cc.Asset>(bundleName: string, names: string[], type?: typeof cc.Asset) {
return new Promise<T[]>((resolve, reject) => {
this.loadBundle(bundleName).
then(bundle => {
bundle.load(names, type, (err: Error, assets: T[]) => {
if (err) {
reject(err)
return
}
resolve(assets)
})
}).
catch(err => {
reject(err)
})
})
}
public static loadRes<T extends cc.Asset>(path: string, type?: typeof cc.Asset) {
return new Promise<T>((resolve, reject) => {
cc.resources.load(path, type, (err: Error, assets: T) => {
if (err) {
reject(err)
return
}
resolve(assets)
})
})
}
public static loadResDir<T extends cc.Asset>(dir: string, type?: typeof cc.Asset) {
return new Promise<T[]>((resolve, reject) => {
cc.resources.loadDir(dir, type, (err: Error, assets: T[]) => {
if (err) {
reject(err)
return
}
resolve(assets)
})
})
}
public static loadResArray<T extends cc.Asset>(names: string[], type?: typeof cc.Asset) {
return new Promise<T[]>((resolve, reject) => {
cc.resources.load(names, type, (err: Error, assets: T[]) => {
if (err) {
reject(err)
return
}
resolve(assets)
})
})
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。