版本:2.3.4

参考:

cocos教程:使用对象池

 

NodePool

cocos的NodePool提供了一个数组,保存和获取数组内对象,并在保存和获取时可执行对象上的unuse和reuse方法。

使用相对简单,看看cocos教程即可。

主要是在获取对象池中实例时,不存在实例,则返回null,不会自动新建。 新建的代码得自己写。

 

cocos对象池源码

CCNodePool.js:

cc.NodePool = function (poolHandlerComp) {
    this.poolHandlerComp = poolHandlerComp;
    this._pool = [];
};
cc.NodePool.prototype = {
    constructor: cc.NodePool,

    size: function () {
        return this._pool.length;
    },

    clear: function () {
        var count = this._pool.length;
        for (var i = 0; i < count; ++i) {
            this._pool[i].destroy();
        }
        this._pool.length = 0;
    },

    put: function (obj) {
        if (obj && this._pool.indexOf(obj) === -1) {
            // Remove from parent, but don't cleanup
            obj.removeFromParent(false);

            // Invoke pool handler
            var handler = this.poolHandlerComp ? obj.getComponent(this.poolHandlerComp) : null;
            if (handler && handler.unuse) {
                handler.unuse();
            }

            this._pool.push(obj);
        }
    },

 
    get: function () {
        var last = this._pool.length-1;
        if (last < 0) {
            return null;
        }
        else {
            // Pop the last object in pool
            var obj = this._pool[last];
            this._pool.length = last;

            // Invoke pool handler
            var handler = this.poolHandlerComp ? obj.getComponent(this.poolHandlerComp) : null;
            if (handler && handler.reuse) {
                handler.reuse.apply(handler, arguments);
            }
            return obj;
        }
    }
};

module.exports = cc.NodePool;

  

 PrefabPool

我自己写了一个针对prefab的对象池。有以下的改进。

1. 全局调用,不需要在使用的地方去new cc.NodePool

2. 在对象池没有缓存实体时,会自动创建并返回实体

3. 对象回收时,根据创建时动态属性poolKey找到对应池子回收

4. 保留了NodePool的unuse和reuse

// Learn TypeScript:
//  - https://docs.cocos.com/creator/manual/en/scripting/typescript.html
// Learn Attribute:
//  - https://docs.cocos.com/creator/manual/en/scripting/reference/attributes.html
// Learn life-cycle callbacks:
//  - https://docs.cocos.com/creator/manual/en/scripting/life-cycle-callbacks.html

const { ccclass, property } = cc._decorator;

/**
 * 预制体对象池
 * @author chenkai 2020.6.11
 */
@ccclass
export default class PrefabPool {
    /**对象池列表 */
    private static poolList = {};

    /**
     * 获取对象
     * @param prefabUrl        预制体路径
     * @param poolHandlerComp  reuse绑定函数
     */
    public static get(prefabUrl:string, poolHandlerComp:Function = null){
        //创建对象池数组
        if(this.poolList[prefabUrl] == null){
            this.poolList[prefabUrl] = [];
        }
        //从对象池获取对象,没有则创建
        let pool = this.poolList[prefabUrl];
        let obj;
        if (pool.length == 0) {
            obj = cc.instantiate(cc.loader.getRes(prefabUrl));
            (obj as any).poolKey = prefabUrl;
        }else{
            obj = pool.pop();
        }
        //执行reuse
        var handler = poolHandlerComp ? obj.getComponent(poolHandlerComp) : null;
        if (handler && handler.reuse) {
            handler.reuse.apply(handler, arguments);
        }
        //返回对象
        return obj;
    }

    /**
     * 回收对象
     * @param obj              实体
     * @param poolHandlerComp  unuse绑定函数
     */
    public static put(obj:cc.Node, poolHandlerComp:Function = null){
        let pool = this.poolList[(obj as any).poolKey];
        //判断对象池存在
        if (pool && pool.indexOf(obj) == -1) {
            //移除舞台
            obj.removeFromParent(false);
            //执行unuse
            var handler = poolHandlerComp ? obj.getComponent(poolHandlerComp) : null;
            if (handler && handler.unuse) {
                handler.unuse();
            }
            //存放对象
            pool.push(obj);
        }
    }

    /**
     * 清理对象池
     * @param prefabUrl 预制体路径
     */
    public static clear(prefabUrl:string){
        let pool = this.poolList[prefabUrl];
        if(pool){
            for (let i = 0,len=pool.length; i < len; i++) {
                pool[i].destroy();
            }
            pool.length = 0;
        }
    }

    /**清理所有对象池 */
    public static clearAll(){
        for(let key in this.poolList){
            this.clear(key);
        }
    }

    /**
     * 对象池长度
     * @param prefabUrl 预制体路径
     */
    public static size(prefabUrl:string) {
        let pool = this.poolList[prefabUrl];
        if(pool){
            return pool.length;
        }
        return 0;
    }
}

  

使用

export class PrefabConst{
    public static Monster001:string = "game/prefab/monster001";//预制体路径
    public static Mosnter002:string = "game/prefab/monster002";
}
 
 
export class GameScene{
 
     onLoad(){
          //获取对象
          let node001:cc.Node = PrefabPool.get(PrefabConst.Monster001,Monster);
          let monster001:Monster = node.getComponent(Monster);
          let node002:cc.Node = PrefabPool.get(PrefabConst.Monster002,Monster);
          let monster002:Monster = node.getComponent(Monster);
          //回收对象
          PrefabPool.put(node001,Monster);
          PrefabPool.put(node002,Monster);
          //清理对象
          PrefabPool.clear(PrefabConst.Monster001);
          PrefabPool.clearAll();
    }
}

  

 

posted on 2020-06-11 11:57  gamedaybyday  阅读(2387)  评论(0编辑  收藏  举报