Cocos Creator 游戏开发之对象池

    技术2022-07-11  78

    前言

    自己写的一个简化版对象池,没什么好说的,就是简单的拿取回收,支持多个对象共同存储。

    对象池类

    import { Queue } from "../../Common/Queue"; export class NodePool { private prefab: cc.Prefab = null; /** 最大初始化数量 */ private maxCount: number = 0; /** 已经拿取的对象数量 */ private spawnCount: number = 0; private nodeLists: Queue<cc.Node> = null; private canvas: cc.Node; private parent: cc.Node; constructor(_prefab: cc.Prefab, _maxCount: number = 20) { this.Inialize(_prefab, _maxCount); } public Inialize(_prefab: cc.Prefab, _maxCount: number = 20) { this.prefab = _prefab; this.maxCount = _maxCount; this.nodeLists = new Queue(_maxCount); //把对象统一放到Canvas/ObjectPools节点下管理 this.canvas = cc.find('Canvas'); this.parent = new cc.Node('ObjectPools'); this.canvas.addChild(this.parent); this.CreateNode(); } public CreateNode() { for (let i = 0; i < this.maxCount; i++) { this.nodeLists.Push(this.AddNode()); } } private AddNode(): cc.Node { let obj: cc.Node = cc.instantiate(this.prefab); this.parent.addChild(obj); obj.active = false; obj.setPosition(cc.Vec2.ZERO) return obj; } /** 拿取对象池对象 */ public Spawn():cc.Node { // console.log('spawn:', this.spawnCount); if (this.spawnCount >= this.maxCount) { this.nodeLists.Push(this.AddNode()); } let obj: cc.Node = this.nodeLists.Pop(); this.spawnCount++; obj.active = true; return obj; } /** 回收对象池对象 */ public UnSpawn(_obj: cc.Node) { // console.log('unspawn:', this.nodeLists.Count); if (this.nodeLists.Count < this.maxCount) { _obj.active = false; this.spawnCount--; this.nodeLists.Push(_obj); } } /** 释放所有对象 */ public ReleaseAll() { this.nodeLists.Clear(); } }

    对象池管理类

    import { NodePool } from "./NodePool"; const { ccclass, property } = cc._decorator; export var PoolData = cc.Class({ name: 'PoolData', properties: { /** 对象名,根据这个获取对象 */ name: 'obj', /** 对象预制体 */ nodePrefab:cc.Prefab, //对象初始化最大数量 maxCount:10, } }); /** * @name JoeyHuang * @date 2020/7/1 13:49:22 * @description 描述 多对象的对象池管理,根据对象名字去获取相应对象 */ @ccclass export default class PoolManager extends cc.Component { public static Instance: PoolManager; //这里设置多少个对象 @property(PoolData) poolDataLists:any=[]; @property maxCount:number=30; private poolMap: Map<string, NodePool> = new Map(); onLoad() { PoolManager.Instance = this; this.Initialize(); } Initialize() { for (let i = 0; i < this.nodePrefabs.length; i++) { this.poolMap.set(this.poolDataLists[i].name, new NodePool(this.poolDataLists[i].nodePrefab, this.poolDataLists[i].maxCount)); } } /** * 根据名字拿取对象 * @param poolName 对象名字 */ public Spawn(poolName:string):cc.Node { if(this.poolMap.has(poolName)) { return this.poolMap.get(poolName).Spawn(); } return null; } /** * 回收对象 * @param poolName 对象名 * @param _node 对象实例 */ public UnSpawn(poolName:string,_node:cc.Node) { if(this.poolMap.has(poolName)) { this.poolMap.get(poolName).UnSpawn(_node); } } }

    用法

    需要把PoolManager挂在一个节点上,空节点就行。给每个对象设置好名字,赋值预制体以及初始化数量,我们拿取对象或者回收对象的时候都需要用到对象名,如图:

    脚本调用

    let obj: cc.Node = PoolManager.Instance.Spawn('whiteParticle');
    Processed: 0.010, SQL: 9