110 lines
3.4 KiB
TypeScript
110 lines
3.4 KiB
TypeScript
import { _decorator, AssetManager, assetManager, instantiate, Node, NodePool, Prefab, resources } from 'cc';
|
||
const { ccclass, property } = _decorator;
|
||
|
||
@ccclass('NodePoolManager')
|
||
export class NodePoolManager {
|
||
private static _instance: NodePoolManager = null;
|
||
private _nodePoolMap: Map<string, NodePool> = null;
|
||
private _prefabCache: Map<string, Prefab> = new Map<string, Prefab>();
|
||
|
||
static get instance() {
|
||
if (this._instance) {
|
||
return this._instance;
|
||
}
|
||
this._instance = new NodePoolManager();
|
||
return this._instance;
|
||
}
|
||
|
||
constructor() {
|
||
this._nodePoolMap = new Map<string, NodePool>();
|
||
}
|
||
|
||
// 内部调用,通过name获取节点池
|
||
getNodePoolByName(name: string): NodePool {
|
||
if (!this._nodePoolMap.has(name)) {
|
||
let nodePool = new NodePool(name);
|
||
this._nodePoolMap.set(name, nodePool)
|
||
}
|
||
let nodePool = this._nodePoolMap.get(name);
|
||
return nodePool
|
||
}
|
||
|
||
getNodeFromPoolStatic(name: string, prefab?: Prefab): Node | null {
|
||
let nodePool = this.getNodePoolByName(name);
|
||
let poolSize = nodePool.size();
|
||
if (poolSize <= 0) {
|
||
let node = instantiate(prefab);
|
||
nodePool.put(node);
|
||
}
|
||
return nodePool.get();
|
||
}
|
||
|
||
async getNodeFromPoolDynamic(name: string, path: string, bundleName?: string): Promise<Node> {
|
||
let nodePool = this.getNodePoolByName(name);
|
||
if (nodePool.size() <= 0) {
|
||
let prefab = await this.loadPrefab(path, bundleName);
|
||
let node = instantiate(prefab);
|
||
nodePool.put(node);
|
||
}
|
||
return nodePool.get();
|
||
}
|
||
|
||
async loadPrefab(path: string, bundleName?: string): Promise<Prefab> {
|
||
let key = bundleName ? `${bundleName}:${path}` : path;
|
||
let cachedPrefab = this._prefabCache.get(key);
|
||
if (cachedPrefab) return cachedPrefab;
|
||
|
||
let loadBundle = async (): Promise<AssetManager.Bundle> => {
|
||
let exist = assetManager.getBundle(bundleName);
|
||
if (exist) return exist;
|
||
return await new Promise<AssetManager.Bundle>((resolve, reject) => {
|
||
assetManager.loadBundle(bundleName, (err, bundle) => {
|
||
if (err) return reject(err);
|
||
resolve(bundle);
|
||
});
|
||
});
|
||
}
|
||
|
||
|
||
let loadFromBundle = bundleName && bundleName.length > 0;
|
||
let bundle = loadFromBundle ? await loadBundle() : resources;
|
||
|
||
let prefabInCache = (bundle as any).get?.(path, Prefab);
|
||
if (prefabInCache) {
|
||
this._prefabCache.set(key, prefabInCache);
|
||
return prefabInCache;
|
||
}
|
||
|
||
let prefab = await new Promise<Prefab>((resolve, reject) => {
|
||
bundle.load(path, Prefab, (e, p) => e ? reject(e) : resolve(p));
|
||
});
|
||
this._prefabCache.set(key, prefab);
|
||
return prefab;
|
||
}
|
||
|
||
putNodeToPool(name: string, node: Node) {
|
||
let nodePool = this.getNodePoolByName(name);
|
||
nodePool.put(node);
|
||
}
|
||
|
||
clearNodePoolByName(name: string) {
|
||
let nodePool = this.getNodePoolByName(name);
|
||
nodePool.clear();
|
||
if (this._nodePoolMap.has(name)) {
|
||
this._nodePoolMap.delete(name);
|
||
}
|
||
}
|
||
|
||
clearAll() {
|
||
this._nodePoolMap.forEach(value => {
|
||
value.clear();
|
||
})
|
||
this._nodePoolMap.clear();
|
||
}
|
||
|
||
static destoryInstance() {
|
||
this._instance = null;
|
||
}
|
||
}
|
||
|