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