引擎:CocosCreator。 语言: TS
前言:最近一个朋友和我聊天吐槽了一下cocosCreator的资源管理问题并问我有没有好的管理方案和方法,但我认为他并没有真正去尝试做一下而是人云亦云的在叙述给我听~没劲!,所以我花了2小时浏览了一下官方文档和尝试,并给了这位朋友回复;记录下来希望能够抛砖引玉获得大家更优秀的方案。
一、静态资源引用的管理
二、动态资源引用的管理
- 看一下引擎为我们提供的资源释放接口:
根据上面释放接口我们可以梳理成两种方式进行管理: 1、使用第一中方式,引用计数我们自定义,然后自己进行管理增加和减少,当自定义对应的资源的引用计数为0,我们手动调用资源释放接口。(不建议使用,使用比较复杂但是可正常实现资源管理) 2、我们只需要调用addRef增加引用计数,decRef减少引用计数,当引用为0的时候系统自动给我们清理。(推荐使用)
cc.assetManager.assets;
cc.resources.get('path/name',cc.SpriteFrame);
- 使用内置bundle和资源图集/图片/预制体为案例封装了一下关于资源释放,其他类型资源和其他bundle都差不多,可自行整理(建议:按场景、界面、窗口等单位去释放,而不是当一个小怪物死亡后立马就进行释放,虽然这样也可以)。
export default class AssetManager {
private cachSpriteAtlas: Map<string, cc.SpriteAtlas> = new Map();
private cachSpritFrames: Map<string, cc.SpriteFrame> = new Map();
private cachPrefabs: Map<string, cc.Prefab> = new Map();
public loadByResources_SpriteAtlas(assetPath: string, assetName: string, assetType: typeof cc.Asset, onComplete: (err: Error, asset: cc.Asset) => void) {
let _assetAtlas = <cc.SpriteAtlas>cc.resources.get(assetPath, assetType);
if (_assetAtlas) {
let _asset = _assetAtlas.getSpriteFrame(assetName);
if (_asset && onComplete) { onComplete(null, _asset); }
if (_asset.refCount <= 1) { _asset.addRef(); }
if (!this.cachSpritFrames.get(assetName)) { this.cachSpritFrames.set(assetName, _asset); }
}
else {
cc.resources.load(assetPath, assetType, (err: Error, assetAtlas: cc.Asset) => {
if (err) {
console.warn("Error:", err);
return;
}
_assetAtlas = <cc.SpriteAtlas>assetAtlas;
let _asset = _assetAtlas.getSpriteFrame(assetName);
if (_asset && onComplete) { onComplete(err, _asset); }
if (_assetAtlas.refCount == 0) { _assetAtlas.addRef(); }
if (_asset.refCount <= 1) { _asset.addRef(); }
if (!this.cachSpriteAtlas.get(assetPath)) { this.cachSpriteAtlas.set(assetPath, _assetAtlas); }
if (!this.cachSpritFrames.get(assetPath + '/' + assetName)) { this.cachSpritFrames.set(assetPath + '/' + assetName, _asset); }
})
}
}
public loadByResources(assetPath: string, assetType: typeof cc.Asset, onComplete: (err: Error, asset: cc.Asset) => void) {
let _asset: cc.Asset = cc.resources.get(assetPath, assetType);
if (_asset) {
if (onComplete) {
onComplete(null, _asset);
}
}
else {
cc.resources.load(assetPath, assetType, (err: Error, asset: cc.Asset) => {
if (err) {
console.warn("Error:", err);
return;
}
if (asset.refCount == 0) { asset.addRef(); }
if (onComplete) { onComplete(err, asset); }
if (assetType == cc.SpriteFrame) {
if (!this.cachSpritFrames.get(assetPath)) { this.cachSpritFrames.set(assetPath, <cc.SpriteFrame>asset); }
}
else if (assetType == cc.Prefab) {
if (!this.cachPrefabs.get(assetPath)) { this.cachPrefabs.set(assetPath, <cc.Prefab>asset); }
}
})
}
}
public releaseByResources(assetType: typeof cc.Asset, path: string = null) {
if (assetType == cc.SpriteAtlas) {
this.releaseTypeAsset(this.cachSpriteAtlas, assetType, path);
}
else if (assetType == cc.SpriteFrame) {
this.releaseTypeAsset(this.cachSpritFrames, assetType, path);
}
else if (assetType == cc.Prefab) {
this.releaseTypeAsset(this.cachPrefabs, assetType, path);
}
}
private releaseTypeAsset(cachAssets: Map<string, cc.Asset>, assetType: typeof cc.Asset, path: string) {
if (path == null) {
cachAssets.forEach((value, key) => {
if (value) {
value.decRef();
}
})
cachAssets.clear();
}
else {
let _key: string = null;
for (const [key, value] of Array.from(cachAssets.entries())) {
if (key == path) {
_key = key;
if (value) { value.decRef();}
break;
}
}
if(_key != null) {
cachAssets.delete(_key);
}
}
}
}
- 因为我不想采用继承的方式去管理,所以记得在其他文件中使用的时候去初始化一下自己。比如:
其他文件.ts
cc.Class NewClass{
private assetManager: AssetManager = null;
onLoad() {
this.assetManager = new AssetManager();
}
start() {
this.assetManager.loadByResources("item", cc.Prefab, (err, asset: cc.Prefab) => {
let tempNode: cc.Node = cc.instantiate(asset)
tempNode.parent = this.node;
tempNode.position = cc.Vec3.ZERO;
})
this.assetManager.loadByResources('UIImage/Bag_zhihuan', cc.SpriteFrame, (err, asset) => {
});
this.assetManager.loadByResources_SpriteAtlas('UIImage/Bag', '100005', cc.SpriteFrame, (err, asset) => {
});
}
onDestroy(){
this.assetManager.releaseByResources(cc.SpriteAtlas)
this.assetManager.releaseByResources(cc.SpriteFrame)
this.assetManager.releaseByResources(cc.Prefab)
this.assetManager.releaseByResources(cc.SpriteAtlas,'UIImage/Bag');
this.assetManager.releaseByResources(cc.SpriteFrame,'UIImage/Bag_zhihuan')
this.assetManager.releaseByResources(cc.SpriteFrame,'UIImage/Bag/100005')
this.assetManager.releaseByResources(cc.Prefab, 'item')
}
}
|