cocos creator从零开发简单框架(04)-资源管理

框架的UIPanel都是预设资源,需要动态加载,而引擎只提供了回调方式加载资源的接口,而回调层次多了会造成代码难以理解,所以需要自己封装异步接口。

场景新建一个Label,内容任意,然后把它拖动到resources目录下并从场景删除。

新建Label

拖动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正确加载了。

动态加载Label

这是正确运行的情况,如果把ResMgr.loadRes<cc.Prefab>('lblTest')修改成ResMgr.loadRes<cc.Prefab>('lblTest2')加载不存在的资源,会发现程序崩溃了(后续代码逻辑不能正常运行),因为没有处理出现错误的情况。

加载错误的Label

现在我们做错误处理,代码如下。

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)
            })
        })
    }
}
本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!