import { Prefab, Node, instantiate } from "cc"; import { UIHelper } from "../common/UIHelper"; import { Framework } from "../Framework"; import { resLoader } from "../res/ResLoader"; import { TimeUtil } from "../util/TimeUtil"; import { NodeEx } from "./NodeEx"; //一维节点池支持Prefab和Node模式 export class NodePool { private _ready: boolean = false; //节点是否初始化完毕 private _size: number = 10; //池大小 private _res: Prefab | Node = null; //资源 private _pool: Node[] = []; //节点列表 private _clear_time: number = 120; //清理时间(秒) private _timer = -1; //定时器uuid private _reinforce = false; //是否是二维池 /** * 初始化节点池 * @param bundle 包名 * @param url 路径 * @param size 节点池大小 * @param clear 节点池清理时间(秒) * @param calback 初始化成功回调 * @param reinforce 是否是二维节点池 */ init(res: Prefab | Node, size: number, clear: number, reinforce?: boolean) init(bundle: string, url: string, size: number, clear: number, calback: Function, reinforce?: boolean) init() { if (this._pool.length > 0) { this.clear() } if(this._res && (this._res instanceof Prefab)){ this._res.decRef(); this._res = null; } this._pool = []; if (arguments) { if (arguments.length == 4) { this._ready = true; this._res = arguments[0]; //如果res在Asset原型链上则引用计数+1 if (this._res instanceof Prefab) { this._res.addRef(); } this._size = arguments[1]; this._clear_time = arguments[2]; if (this._clear_time > 0) { this._timer = Framework.time.schedule(() => { this._clearPool(); }, this._clear_time); } this._reinforce = arguments[3] ? arguments[3] : false; } else { this._size = arguments[2]; this._clear_time = arguments[3]; resLoader.load(arguments[0], arguments[1], Prefab, (error: Error, prefab: Prefab) => { if (error) { console.error(error); } else { this._res = prefab; this._res.addRef(); this._ready = true; arguments[4] && arguments[4](); if (this._clear_time > 0) { this._timer = Framework.time.schedule(() => { this._clearPool(); }, this._clear_time); } } }); this._reinforce = arguments[5] ? arguments[5] : false; } } } private _clearPool() { if (this._ready) { let cur_time = TimeUtil.getTimeEx(0); this._pool.forEach((node, idx) => { if (cur_time - node.getComponent(NodeEx).useTime >= this._clear_time) { node.getComponent(NodeEx)?.unuse(); node.destroy(); this._pool.splice(idx, 1); } }); } } /** * 设置节点池大小 * @param size 大小 */ setPoolSize(size: number) { this._size = size; } /** * 获取节点 * @param parent 父节点 * @param val 自定义参数 */ getNode(parent: Node = null, ...val: any[]) { if (this._ready) { let node = ((this._pool.length > 0) ? this._pool.shift() : instantiate(this._res)) as Node; if (!node.isValid) { while (true) { node = ((this._pool.length > 0) ? this._pool.shift() : instantiate(this._res)) as Node; if (node.isValid) { break; } } } node.active = true; if (parent) { UIHelper.setLayer(node, parent.layer); parent.addChild(node); } //如果是二维池则由二维池调用 let template = node.getComponent(NodeEx); (!this._reinforce) && template.reuse(...val); return template; } return null; } /** * 归还节点,如果节点池已满将被销毁 */ putNode(template: NodeEx) { if (template && template.isValid) { template.unuse(); if (this._pool.length >= this._size) { template.node.destroy(); } else { template.node.removeFromParent(); template.useTime = TimeUtil.getTimeEx(0); template.node.active = false; this._pool.push(template.node); } } } /** * 清理节点池 */ clear() { (this._timer != -1) && Framework.time.unschedule(this._timer); // for (let node of this._pool) { // node.destroy(); // } if (this._res) { // (this._res instanceof Prefab) ? this._res.decRef() : this._res.destroy(); console.log("NodePool clear",(this._res && this._res.name)); if(this._res instanceof Prefab) this._res.decRef() ; this._res = null; } this._pool = []; this._ready = false; (this._timer > 0) && Framework.time.unschedule(this._timer); this._timer = -1; } }