//********************* // create by 流云 // time: 2020.12.18 // desc: 资源管理器 //********************* import { Asset, assetManager, AssetManager, _decorator } from "cc"; const { ccclass } = _decorator; /** * 开箱即用资源管理器 */ @ccclass export class ResManager { private static _ins: ResManager = null; public static get Ins() { if (!this._ins) this._ins = new ResManager(); return this._ins; } private _res_map: Map = new Map(); getRes({ bundle, path, name, type = Asset, canRelease = true, onComplete = null }) { let k = bundle + path + name; let res = this._res_map.get(k); if (!res) { res = new ResRecord(); this._res_map.set(k, res); res.canRelease = canRelease; } res.bundle = bundle; res.path = path; res.name = name; if (!res.res) { this.loadBundle(bundle, (b) => { this.loadRes(b, path + name, (asset) => { res.res = asset; //res.res.addRef(); if (onComplete) { onComplete(res.res); } }, type); }) } else { if (onComplete) { onComplete(res.res); } } } /** * 同步获取资源 * @param bundleName 资源包名称 * @param path 路径 * @param resName 名称 * @param type 类型 * @param canRelease 是否可释放 * @returns */ async getResAsync(bundleName, path, resName, type = Asset, canRelease = true) { let k = bundleName + path + resName; let res = this._res_map.get(k); if (!res) { res = new ResRecord(); this._res_map.set(k, res); res.canRelease = canRelease; } res.bundle = bundleName; res.path = path; res.name = resName; if (!res.res) { let b = await this.loadBundle(bundleName); if (!b) return null; res.res = await this.loadRes(b, path + resName, null, type); //if (res.res) res.res.addRef(); } return res.res; } /** * 预加载bundle * @param bundleName bundle名称 * @param onProgress 进度回调 * @param onComplete 完成回调 */ preLoadBundle(bundleName, onProgress = null, onComplete = null, path = "/") { let bundle = assetManager.getBundle(bundleName); if (bundle) { bundle.preloadDir(path, onProgress, onComplete); return; } this.loadBundle(bundleName, (b: AssetManager.Bundle) => { b.preloadDir(path, onProgress, onComplete); }) } /** * 预加载资源包 * @param resComfArr 资源包数组,例如: * [ * {name:"gameBg",bundle:"game",path:"img/",canRelease:true}, * {name:"gametitle",bundle:"game",path:"img/",canRelease:true}, * {name:"gametext",bundle:"game",path:"img/",canRelease:true} * ] * @param onProgress 加载进度回调 * @param onComplete 加载完成回调 */ preLoadModeRes(resComfArr, onProgress: Function = null, onComplete: Function = null) { try { let maxCount = resComfArr.length; let curentCount = 0; for (let i = 0; i < resComfArr.length; i++) { let ritem = resComfArr[i]; this.loadBundle(ritem.bundle, (b) => { this.preLoadRes(b, ritem.path + ritem.name, () => { curentCount++; if (onProgress) { onProgress(curentCount, maxCount); } if (onComplete && curentCount == maxCount) { onComplete(); } }) }) } } catch (error) { console.log("预加载模块资源出错", error); } } /** * 加载资源包 * @param resComfArr 资源包数组,例如: * [ * {name:"gameBg",bundle:"game",path:"img/",canRelease:true}, * {name:"gametitle",bundle:"game",path:"img/",canRelease:true}, * {name:"gametext",bundle:"game",path:"img/",canRelease:true} * ] * @param onProgress 加载进度回调 * @param onComplete 加载完成回调 */ loadModeRes(resComfArr, onProgress: Function = null, onComplete: Function = null) { try { let maxCount = resComfArr.length; let curentCount = 0; for (let i = 0; i < resComfArr.length; i++) { let ritem = resComfArr[i]; let k = ritem.bundle + ritem.path + ritem.name; let r = this._res_map.get(k); if (r && r.res && r.res.isValid) { curentCount++; if (onProgress) { onProgress(curentCount, maxCount); } if (onComplete && curentCount == maxCount) { onComplete(); } continue; } if (!r) { r = new ResRecord(); this._res_map.set(k, r); } r.bundle = ritem.bundle; r.canRelease = ritem.canRelease; r.key = k; r.name = ritem.name; r.path = ritem.path; this.loadBundle(ritem.bundle, (b) => { this.loadRes(b, ritem.path + ritem.name, (res) => { r.res = res; curentCount++; if (onProgress) { onProgress(curentCount, maxCount); } if (onComplete && curentCount == maxCount) { onComplete(); } }) }) } } catch (error) { console.log("加载模块资源出错", error); } } /** * 释放单个资源 * @param bundleName 资源包名 * @param path 路径 * @param resName 资源名称 */ releaseRes(bundleName, path, resName) { let k = bundleName + path + resName; let r = this._res_map.get(k); if (r && r.res) { r.res.decRef(); if (r.res.refCount == 0) r.res = null; } } /** * 释放模块包资源 * @param resComfArr 资源模块配置包 */ releaseModeRes(resComfArr) { try { for (let i = 0; i < resComfArr.length; i++) { let item = resComfArr[i]; this.releaseRes(item.bundle, item.path, item.name); } } catch (error) { console.log("释放资源出错", error); } } releaseAll() { this._res_map.forEach((v, k) => { if (v.res && v.canRelease) { v.res.decRef(); if (v.res.refCount == 0) { v.res = null; } } }) } public async loadBundle(bundleName, onComplete: Function = null) { return new Promise((resolve, reject) => { assetManager.loadBundle(bundleName, (err, bundle) => { if (err) { console.log(`加载Bundle:${bundleName}错误`, err); if (onComplete) onComplete(null); resolve(null); } else { if (onComplete) onComplete(bundle); resolve(bundle); } }) }) } private async loadRes(bundle: AssetManager.Bundle, assetPath, onComplete: Function = null, type = Asset) { return new Promise((resolve, reject) => { bundle.load(assetPath, type, (err, asset) => { if (err) { console.log(`加载Bundle:${bundle.name},path:${assetPath}资源错误`, err); if (onComplete) onComplete(null); resolve(null); } else { if (onComplete) onComplete(asset); resolve(asset); } }) }) } private preLoadRes(bundle: AssetManager.Bundle, assetPath, onComplete: Function = null) { console.log(`预加载Bundle:${bundle.name},path:${assetPath}资源开始11111`,bundle); bundle.preload(assetPath, (err, asset) => { console.log(`预加载Bundle:${bundle.name},path:${assetPath}资源完成`,err,asset); if (err) { console.log(`预加载Bundle:${bundle.name},path:${assetPath}资源错误`, err); if (onComplete) onComplete(null); } else { if (onComplete) onComplete(asset); } }) } } class ResRecord { key = ``; bundle = ``; path = ``; name = ``; type = Asset; res: Asset = null; canRelease = true; }