123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214 |
- /**
- * Prefab对象池类
- * 1. 占用并复用资源,使用Mgr.ResMgr加载资源并标记为资源池占用
- * 2. Prefab对象管理、缓存、创建,每个Prefab资源对应一个池子
- * 3. 针对每个Prefab对象池的水位控制
- * 4. freePrefab 里面检测node是否有效,无效的node报错提示,_createCount--
- *
- * @format
- */
- import {BaseUI} from '../ui/BaseUI'
- import {Log} from '../utils/LogUtils'
- import {Data} from '../GameControl'
- export interface IPrefabPool {
- baseUI: BaseUI
- prefabReset(): void
- }
- export class PrefabPool {
- private _createCount: number = 0
- private _waterMark: number = 10
- private readonly _url: string
- private readonly _res: cc.Prefab = null
- private _nodes: cc.Node[] = []
- public constructor(url: string, prefab: cc.Prefab) {
- this._url = url
- this._res = prefab
- }
- /**
- * 获取url
- */
- public getUrl(): string {
- return this._url
- }
- /**
- * 获取prefab
- * @param url prefab的url
- */
- public getPrefab(): cc.Node {
- if (this._nodes.length > 0) {
- const node = this._nodes.pop()
- if (cc.isValid(node)) {
- node.active = true
- return node
- }
- node.destroy()
- this._createCount++
- return cc.instantiate(this._res)
- }
- this._createCount++
- return cc.instantiate(this._res)
- }
- /**
- * 回收prefab
- * @param url prefab的url
- * @param node
- */
- public freePrefab(node: cc.Node) {
- if (!(node && cc.isValid(node))) {
- cc.error('[ERROR] PrefabPool: freePrefab: isValid node')
- this._createCount--
- return
- }
- if (this._waterMark < this._nodes.length) {
- this._createCount--
- Log.warn('PrefabPoolManager freePrefab: waterMark is below')
- node.destroy()
- } else {
- node.stopAllActions()
- node.parent = null
- node.position = cc.Vec3.ZERO
- node.scale = 1
- const components = node['_components']
- components.forEach(value => {
- if (value['prefabReset']) {
- value.prefabReset()
- }
- })
- this._nodes.push(node)
- }
- }
- /**
- * 设置回收池缓存个数
- * @param waterMark 缓存个数
- */
- public setWaterMark(waterMark: number) {
- if (waterMark > this._waterMark) {
- this._waterMark = waterMark
- }
- }
- /**
- * 池子里的prefab是否都没有使用
- */
- public isUnuse() {
- if (this._nodes.length > this._createCount) {
- cc.error('PrefabPool: _nodes.length > _createCount')
- }
- return this._nodes.length == this._createCount
- }
- /**
- * 清空prefab
- */
- public destroy() {
- // 清空节点、回收资源
- for (const node of this._nodes) {
- node.destroy()
- }
- this._createCount -= this._nodes.length
- this._nodes.length = 0
- cc.assetManager.releaseAsset(this._res)
- }
- // 只清理池子不回收
- public clearPool() {
- for (const node of this._nodes) {
- node.destroy()
- }
- this._createCount -= this._nodes.length
- this._nodes.length = 0
- }
- }
- export class PrefabPoolManager {
- private _pools: Map<string, PrefabPool> = new Map<string, PrefabPool>()
- // Prefab url loadRes时待处理的callback
- private finishCallbackMap: Map<string, any[]> = new Map<string, any[]>()
- public initPrefabPoolByPrefab(url: string, prefab: cc.Prefab, waterMark: number = 64) {
- if (!this._pools.has(url)) {
- const pool = new PrefabPool(url, prefab)
- pool.setWaterMark(waterMark)
- this._pools.set(url, pool)
- }
- }
- //初始化节点对
- public initPoolNode(poolKey: string, prefab: cc.Prefab, waterMark: number = 64) {
- let pool = Data.main.itemsPoolMap.get(poolKey)
- if (!pool) {
- pool = new cc.NodePool()
- }
- for (let i = pool.size(); i < waterMark; ++i) {
- let obj = cc.instantiate(prefab)
- pool.put(obj)
- }
- Data.main.itemsPoolMap.set(poolKey, pool)
- }
- /**
- * 获取prefab池
- * @param url prefab的url
- */
- public getPool(url: string): PrefabPool {
- return this._pools.get(url)
- }
- /**
- * 判断是不是有prefab池
- * @param url prefab的url
- */
- public hasPool(url: string) {
- return this._pools.has(url)
- }
- /**
- * 销毁prefab池
- * @param url prefab的url
- */
- public destroyPool(url: string) {
- if (this._pools.has(url)) {
- this._pools.get(url).destroy()
- this._pools.delete(url)
- }
- }
- /**
- * 初始化预设池返回实例化节点,并返回Promise
- */
- public getNodeAsync(
- url: string,
- bundle: cc.AssetManager.Bundle = cc.resources,
- waterMark: number = 64,
- ): Promise<cc.Node> {
- return new Promise((resolve, reject) => {
- if (this._pools.has(url)) {
- let pool = this._pools.get(url)
- resolve(pool.getPrefab())
- } else {
- bundle.load(url, cc.Prefab, (error, res: cc.Prefab) => {
- let pool: PrefabPool = null
- if (!error) {
- pool = new PrefabPool(url, res)
- pool.setWaterMark(waterMark)
- this._pools.set(url, pool)
- resolve(pool.getPrefab())
- } else {
- reject(null)
- }
- })
- }
- })
- }
- public reset() {
- this.finishCallbackMap.clear()
- this._pools.forEach(value => {
- this.destroyPool(value.getUrl())
- })
- }
- }
|