cocos优化妙招:NodePool 节点池管理节点,搭木桥小游戏实践

1,017 阅读3分钟

NodePool 节点池管理节点

之前了解过mysql的数据库连接池,创建数据库连接是一个很耗时的操作,但是一个http网络请求,就要创建与销毁一个连接,消耗时间与浪费资源,于是有了数据库连接池。 在 cocos creater 中也有一个池子,管理node节点的池子,cc里面的NodePool。创建节点与销毁节点也是比较消耗时间与计算量和内存的操作,重新渲染需要CPU计算,GPU处理,增加 draw call。

screenshot-20211116-205530.png

  1. 导入 NodePool
import { NodePool } from "cc";
  1. 右键转到定于查看 NodePool 源码介绍

    export class NodePool {
        /**
         * @en The pool handler component, it could be the class name or the constructor.
         * @zh 缓冲池处理组件,用于节点的回收和复用逻辑,这个属性可以是组件类名或组件的构造函数。
         */
        poolHandlerComp?: Constructor<IPoolHandlerComponent> | string;
        /**
         * @en
         * Constructor for creating a pool for a specific node template (usually a prefab).
         * You can pass a component (type or name) argument for handling event for reusing and recycling node.
         * @zh
         * 使用构造函数来创建一个节点专用的对象池,您可以传递一个组件类型或名称,用于处理节点回收和复用时的事件逻辑。
         * @param poolHandlerComp @en The constructor or the class name of the component to control the unuse/reuse logic. @zh 处理节点回收和复用事件逻辑的组件类型或名称。
         * @example
         * import { NodePool, Prefab } from 'cc';
         *  properties: {
         *      template: Prefab
         *     },
         *     onLoad () {
         *       // MyTemplateHandler is a component with 'unuse' and 'reuse' to handle events when node is reused or recycled.
         *       this.myPool = new NodePool('MyTemplateHandler');
         *     }
         *  }
         */
        constructor(poolHandlerComp?: Constructor<IPoolHandlerComponent> | string);
        /**
         * @en The current available size in the pool
         * @zh 获取当前缓冲池的可用对象数量
         */
        size(): number;
        /**
         * @en Destroy all cached nodes in the pool
         * @zh 销毁对象池中缓存的所有节点
         */
        clear(): void;
        /**
         * @en Put a new Node into the pool.
         * It will automatically remove the node from its parent without cleanup.
         * It will also invoke unuse method of the poolHandlerComp if exist.
         * @zh 向缓冲池中存入一个不再需要的节点对象。
         * 这个函数会自动将目标节点从父节点上移除,但是不会进行 cleanup 操作。
         * 这个函数会调用 poolHandlerComp 的 unuse 函数,如果组件和函数都存在的话。
         * @example
         * import { instantiate } from 'cc';
         * const myNode = instantiate(this.template);
         * this.myPool.put(myNode);
         */
        put(obj: Node): void;
        /**
         * @en Get a obj from pool, if no available object in pool, null will be returned.
         * This function will invoke the reuse function of poolHandlerComp if exist.
         * @zh 获取对象池中的对象,如果对象池没有可用对象,则返回空。
         * 这个函数会调用 poolHandlerComp 的 reuse 函数,如果组件和函数都存在的话。
         * @param args - 向 poolHandlerComp 中的 'reuse' 函数传递的参数
         * @example
         *   let newNode = this.myPool.get();
         */
        get(...args: any[]): Node | null;
    }
  1. 定义一个 nodeList ,表示视图中展示的节点,此例子视图中一共展示 4 个需要动态管理的节点,实例化 NodePool
  private nodeList: Node[] = [];
  // 实例化 NodePool
  private nodePool: NodePool = new NodePool();
  1. 将场景中原始的节点放入动态节点管理
    // 将场景中原始的节点放入动态节点管理
    this.nodeList.push(this.curPlat);
    this.nodeList.push(this.nextPlat);
  1. 从节点池拿一个节点,节点池没有就新实例化一个
    // 创建一个桥墩
    // 从节点池拿一个节点,节点池没有就新实例化一个 
    let newPlat = this.nodePool.get() || instantiate(this.nextPlat);
    if (this.nodeList.length <= 4) {
      this.nodeList.push(newPlat);
    } else {
      // 同步数据
      this.nodePool.put(this.nodeList[0]);
      this.nodeList.splice(0, 1);
    }

搭木桥小游戏实践

screenshot-20211116-205647.png

代码地址

gitee.com/clig/make-b…

在线游戏

手机H5版在线玩

clig.gitee.io/make-bridge…