NodePool.ts 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. import { Prefab, Node, instantiate } from "cc";
  2. import { UIHelper } from "../common/UIHelper";
  3. import { Framework } from "../Framework";
  4. import { resLoader } from "../res/ResLoader";
  5. import { TimeUtil } from "../util/TimeUtil";
  6. import { NodeEx } from "./NodeEx";
  7. //一维节点池支持Prefab和Node模式
  8. export class NodePool {
  9. private _ready: boolean = false; //节点是否初始化完毕
  10. private _size: number = 10; //池大小
  11. private _res: Prefab | Node = null; //资源
  12. private _pool: Node[] = []; //节点列表
  13. private _clear_time: number = 120; //清理时间(秒)
  14. private _timer = -1; //定时器uuid
  15. private _reinforce = false; //是否是二维池
  16. /**
  17. * 初始化节点池
  18. * @param bundle 包名
  19. * @param url 路径
  20. * @param size 节点池大小
  21. * @param clear 节点池清理时间(秒)
  22. * @param calback 初始化成功回调
  23. * @param reinforce 是否是二维节点池
  24. */
  25. init(res: Prefab | Node, size: number, clear: number, reinforce?: boolean)
  26. init(bundle: string, url: string, size: number, clear: number, calback: Function, reinforce?: boolean)
  27. init() {
  28. if (this._pool.length > 0) {
  29. this.clear()
  30. }
  31. if(this._res && (this._res instanceof Prefab)){
  32. this._res.decRef();
  33. this._res = null;
  34. }
  35. this._pool = [];
  36. if (arguments) {
  37. if (arguments.length == 4) {
  38. this._ready = true;
  39. this._res = arguments[0];
  40. //如果res在Asset原型链上则引用计数+1
  41. if (this._res instanceof Prefab) {
  42. this._res.addRef();
  43. }
  44. this._size = arguments[1];
  45. this._clear_time = arguments[2];
  46. if (this._clear_time > 0) {
  47. this._timer = Framework.time.schedule(() => {
  48. this._clearPool();
  49. }, this._clear_time);
  50. }
  51. this._reinforce = arguments[3] ? arguments[3] : false;
  52. } else {
  53. this._size = arguments[2];
  54. this._clear_time = arguments[3];
  55. resLoader.load(arguments[0], arguments[1], Prefab, (error: Error, prefab: Prefab) => {
  56. if (error) {
  57. console.error(error);
  58. } else {
  59. this._res = prefab;
  60. this._res.addRef();
  61. this._ready = true;
  62. arguments[4] && arguments[4]();
  63. if (this._clear_time > 0) {
  64. this._timer = Framework.time.schedule(() => {
  65. this._clearPool();
  66. }, this._clear_time);
  67. }
  68. }
  69. });
  70. this._reinforce = arguments[5] ? arguments[5] : false;
  71. }
  72. }
  73. }
  74. private _clearPool() {
  75. if (this._ready) {
  76. let cur_time = TimeUtil.getTimeEx(0);
  77. this._pool.forEach((node, idx) => {
  78. if (cur_time - node.getComponent(NodeEx).useTime >= this._clear_time) {
  79. node.getComponent(NodeEx)?.unuse();
  80. node.destroy();
  81. this._pool.splice(idx, 1);
  82. }
  83. });
  84. }
  85. }
  86. /**
  87. * 设置节点池大小
  88. * @param size 大小
  89. */
  90. setPoolSize(size: number) {
  91. this._size = size;
  92. }
  93. /**
  94. * 获取节点
  95. * @param parent 父节点
  96. * @param val 自定义参数
  97. */
  98. getNode(parent: Node = null, ...val: any[]) {
  99. if (this._ready) {
  100. let node = ((this._pool.length > 0) ? this._pool.shift() : instantiate(this._res)) as Node;
  101. if (!node.isValid) {
  102. while (true) {
  103. node = ((this._pool.length > 0) ? this._pool.shift() : instantiate(this._res)) as Node;
  104. if (node.isValid) {
  105. break;
  106. }
  107. }
  108. }
  109. node.active = true;
  110. if (parent) {
  111. UIHelper.setLayer(node, parent.layer);
  112. parent.addChild(node);
  113. }
  114. //如果是二维池则由二维池调用
  115. let template = node.getComponent(NodeEx);
  116. (!this._reinforce) && template.reuse(...val);
  117. return template;
  118. }
  119. return null;
  120. }
  121. /**
  122. * 归还节点,如果节点池已满将被销毁
  123. */
  124. putNode(template: NodeEx) {
  125. if (template && template.isValid) {
  126. template.unuse();
  127. if (this._pool.length >= this._size) {
  128. template.node.destroy();
  129. } else {
  130. template.node.removeFromParent();
  131. template.useTime = TimeUtil.getTimeEx(0);
  132. template.node.active = false;
  133. this._pool.push(template.node);
  134. }
  135. }
  136. }
  137. /**
  138. * 清理节点池
  139. */
  140. clear() {
  141. (this._timer != -1) && Framework.time.unschedule(this._timer);
  142. // for (let node of this._pool) {
  143. // node.destroy();
  144. // }
  145. if (this._res) {
  146. // (this._res instanceof Prefab) ? this._res.decRef() : this._res.destroy();
  147. console.log("NodePool clear",(this._res && this._res.name));
  148. if(this._res instanceof Prefab) this._res.decRef() ;
  149. this._res = null;
  150. }
  151. this._pool = [];
  152. this._ready = false;
  153. (this._timer > 0) && Framework.time.unschedule(this._timer);
  154. this._timer = -1;
  155. }
  156. }