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