作为写了很多年C++的人来说,管理好内存释放还是很在意的,手动加载的资源要释放干净还是要注意一些东西的,看过坛里一些同学的文章就自己整了个管理器Demo,中心思想还是加载时利用getDependsRecursively获取所有的相关资源然后用引用计数做好记录,释放时通过引用计数去释放来解决多个节点共用资源的问题。
源码地址:https://gitee.com/jinghuashuiyue2017/ResLoadManager/tree/master/ResManager/assets
贴个主要代码:
function ResInfo() {
this.path = “”; //资源路径
this.type = null; //资源类型
this.uuids = {}; //使用的资源id
this.obj = null; //资源对象
this.ref = 0; //引用计数
}
window.ResMgr = {
resPool: {},
uuidTable: {},
//加载资源 LoadRes: function(path, type, callback) { if (path in ResMgr.resPool) { return false; } cc.loader.loadRes(path, type, function (err, prefab) { //node = cc.instantiate(prefab); if (err==null) { if (path in ResMgr.resPool) { cc.log("loadRes: "+path+" err:already exist"); if (callback!=null) { callback(err,path); } return; } let newInfo = new ResInfo(); newInfo.path = path; newInfo.obj = prefab; newInfo.type = type; //记录所有相关资源 for (let key of cc.loader.getDependsRecursively(prefab)) { newInfo.uuids[key] = true; if (key in ResMgr.uuidTable) { ResMgr.uuidTable[key] += 1; } else{ ResMgr.uuidTable[key] = 1; } //cc.log(path+"(getDependsRecursively):"+key); } ResMgr.resPool[path] = newInfo; } cc.log("loadRes: "+path+" err:"+err); if (callback!=null) { callback(err,path); } }); return true; }, //获取实例 GetInstance: function(path) { let p = this.resPool[path]; if(p!=null){ p.ref++; if (p.type==cc.Prefab) { return cc.instantiate(p.obj); } else{ return p.obj; } } return null; }, GetInstanceArrary: function(path, num) { let arr = new Array(); let p = this.resPool[path]; if(p!=null && num>0){ for (let index = 0; index < num; index++) { if (p.type==cc.Prefab) { arr.push(cc.instantiate(p.obj)); } else{ arr.push(p.obj); } } p.ref+=num; } return arr; }, //释放实例 ReleaseInstance: function(path, num=1) { let p = this.resPool[path]; if(p!=null){ p.ref -= num; //释放资源 if (p.ref<=0) { this._ReleaseRes(p); } } }, //释放资源 _ReleaseRes: function(p) { //cc.loader.release(Object.keys(p.uuids)); Object.keys(p.uuids).forEach(function(key){ //cc.log(key+": "+LoadRes.uuidTable[key]); ResMgr.uuidTable[key]--; if (ResMgr.uuidTable[key] > 0) { delete p.uuids[key]; } else{ delete ResMgr.uuidTable[key]; } }); cc.loader.release(Object.keys(p.uuids)); delete this.resPool[p.path]; }};
还有些情况还没考虑到,比如由于加载是异步的,加载还没完成的同时去释放相同资源可能会出问题