PoolManager.ts 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. import { _decorator, Component, instantiate, Node, Prefab, Vec3 } from 'cc';
  2. const { ccclass, property } = _decorator;
  3. /**
  4. * 对象池管理器
  5. * 功能:
  6. * 1. 管理游戏对象的复用
  7. * 2. 减少频繁创建/销毁对象的性能开销
  8. * 3. 支持Prefab和Node两种类型的对象池
  9. */
  10. @ccclass('PoolManager')
  11. export class PoolManager extends Component {
  12. // 对象池存储(改为更准确的名称)
  13. private static _objectPools = new Map<string, Node[]>();
  14. /**
  15. * 从对象池获取节点(支持Prefab或Node)
  16. * @param prefab - Prefab资源或节点模板
  17. * @param parent - 可选父节点
  18. * @returns 可复用的节点实例
  19. */
  20. public static getNode(prefab: Prefab | Node, parent?: Node): Node {
  21. const poolKey = prefab instanceof Prefab ? prefab.data.name : prefab.name;
  22. let node: Node = null;
  23. //从对象池获取可用节点
  24. const pool = this._objectPools.get(poolKey);
  25. if(pool?.length > 0) {
  26. node = pool.pop();
  27. }else {
  28. node = instantiate(prefab) as Node;
  29. }
  30. //初始化节点状态
  31. if (node) {
  32. node.active = true;
  33. node.position = Vec3.ZERO;
  34. if(parent) {
  35. node.setParent(parent);
  36. }
  37. }
  38. return node;
  39. }
  40. /**
  41. * 通过名称从对象池获取节点
  42. * @param poolKey - 对象池键名
  43. * @param parent - 可选父节点
  44. * @returns 可复用的节点实例(如果没有则返回null)
  45. */
  46. public static getName(poolKey: string, parent?: Node): Node | null {
  47. const pool = this._objectPools.get(poolKey);
  48. const node = pool?.pop();
  49. if(node) {
  50. node.active = true;
  51. if(parent){
  52. node.setParent(parent);
  53. }
  54. }
  55. return node ?? null;
  56. }
  57. /**
  58. * 将节点回收到对象池
  59. * @param node - 要回收的节点
  60. */
  61. public static putNode(node: Node): void {
  62. if (!node?.isValid || !node) return;
  63. const poolKey = node.name;
  64. //清理节点状态
  65. node.removeFromParent();
  66. node.active = false;
  67. //存入对象池
  68. if(poolKey) {
  69. if(!this._objectPools.has(poolKey)) {
  70. this._objectPools.set(poolKey, []);
  71. }
  72. this._objectPools.get(poolKey).push(node);
  73. }else{//没有有效名称的节点直接销毁
  74. node.destroy();
  75. }
  76. }
  77. /**
  78. * 获取指定对象池的大小
  79. * @param poolKey - 对象池键名
  80. * @returns 对象池中可用节点的数量
  81. */
  82. public static getPoolSize(poolKey: string): number {
  83. return this._objectPools.get(poolKey)?.length ?? 0;
  84. }
  85. /**
  86. * 清空指定对象池
  87. * @param poolKey - 要清空的对象池键名
  88. */
  89. public static clearPool(poolKey: string): void {
  90. const pool = this._objectPools.get(poolKey);
  91. if (pool) {
  92. pool.forEach(node => node.destroy());
  93. this._objectPools.delete(poolKey);
  94. }
  95. }
  96. /**
  97. * 清空所有对象池
  98. */
  99. public static clearAll(): void {
  100. this._objectPools.forEach((pool, key) => {
  101. pool.forEach(node => node.destroy());
  102. });
  103. this._objectPools.clear();
  104. }
  105. }