【工具】Cocos Creator 對象池(NodePool,自定義預制體對象池)


版本: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();
    }
}

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM