feat: update object pooling

main
tiendat3699 2024-03-06 22:10:31 +07:00
parent 1912f52b83
commit 4d97fc35ea
5 changed files with 60 additions and 53 deletions

View File

@ -962,6 +962,12 @@
"__prefab": {
"__id__": 70
},
"rigidbody": {
"__id__": 67
},
"collider": {
"__id__": 65
},
"_id": ""
},
{

View File

@ -10,10 +10,12 @@ import {
IPhysics2DContact,
RigidBody2D,
} from 'cc';
import IPoolable from '../Pool/IPoolable';
import Utilities from '../Utilities/Utilities';
const { ccclass, property } = _decorator;
@ccclass('Ball')
export class Ball extends Component {
export class Ball extends Component implements IPoolable {
@property({ visible: true, type: CCFloat })
public maxSpeed: number;
@property({ visible: true, type: RigidBody2D })
@ -47,4 +49,12 @@ export class Ball extends Component {
// console.log(otherCollider.tag, otherCollider.node.name);
this.hitted = false;
}
reuse() {
console.log('use');
}
unuse() {
console.log('unuse');
}
}

View File

@ -1,6 +1,6 @@
import { _decorator, Component, Prefab } from 'cc';
import { _decorator, Component, Prefab, Node } from 'cc';
import ObjectPool from '../Pool/ObjectPool';
import Utilities from '../Utilities/Utilities';
import { Ball } from '../Gameplay/Ball';
const { ccclass, property } = _decorator;
@ccclass('GameManager')
@ -19,15 +19,7 @@ export class GameManager extends Component {
public score = 0;
protected onLoad(): void {
this._ballPool = new ObjectPool(this._ballPrefab, 10, false);
}
protected async start() {
while (true) {
const ball = this._ballPool.get(this.node);
ball.setWorldPosition(this.node.worldPosition);
await Utilities.delay(1000);
}
this._ballPool = new ObjectPool(this._ballPrefab, 10, false, Ball);
}
public onRevive() {

View File

@ -1,4 +1,4 @@
export default interface IPoolable {
unuse(): void;
reuse(): void;
reuse();
unuse();
}

View File

@ -1,10 +1,12 @@
import { Component, Node, Prefab, __private, director, instantiate } from 'cc';
import { Component, Node, Prefab, director, instantiate } from 'cc';
import IPoolable from './IPoolable';
export default class ObjectPool {
private _inactives: Node[] = [];
private _actives: Node[] = [];
private _prefab: Prefab;
private _expandable;
private _poolHandlerComp: new () => any;
public get countInactive() {
return this._inactives.length;
@ -18,68 +20,65 @@ export default class ObjectPool {
return this.countInactive + this.countActive;
}
constructor(prefab: Prefab, size: number, expandable = true) {
this._expandable = expandable;
constructor(prefab: Prefab, size: number, expandable = true, poolHandlerComp?: new () => any | string) {
this._prefab = prefab;
this._expandable = expandable;
this._poolHandlerComp = poolHandlerComp;
for (let i = 0; i < size; ++i) {
let obj = instantiate(this._prefab); // create node instance
obj.active = false;
this._inactives.push(obj); // populate your pool with put method
obj.removeFromParent();
this._inactives.push(obj);
}
}
public get(parent?: Node): Node;
public get<T extends Component>(
parent?: Node,
classConstructor?:
| __private._types_globals__Constructor<T>
| __private._types_globals__AbstractedConstructor<T>,
): T;
public get<T extends Component>(parent?: Node, classConstructor?: new () => T): T;
public get<T extends Component>(
parent?: Node,
classConstructor?:
| __private._types_globals__Constructor<T>
| __private._types_globals__AbstractedConstructor<T>,
): T | Node {
public get<T extends Component>(parent?: Node, classConstructor?: new () => T): T | Node {
let obj: Node = null;
let p = parent || director.getScene();
if (this._inactives.length > 0) {
// use size method to check if there're nodes available in the pool
// Pop the last object in pool
obj = this._inactives.pop();
obj.setParent(p);
this._actives.push(obj);
} else if (this._expandable) {
// if not enough node in the pool, we call cc.instantiate to create node
obj = instantiate(this._prefab);
obj.setParent(p);
this._actives.push(obj);
} else {
obj = this._actives.shift();
this._actives.push(obj);
}
obj.active = true;
if (classConstructor) {
return obj.getComponent(classConstructor);
obj.setParent(p);
this._actives.push(obj);
// Invoke pool handler
const handler = this._poolHandlerComp ? obj.getComponent(this._poolHandlerComp) : null;
if (handler) {
(handler as unknown as IPoolable)?.reuse();
}
if (classConstructor) {
return handler == classConstructor ? handler : obj.getComponent(classConstructor);
}
return obj;
}
public release(obj: Node);
public release<T extends Component>(obj: T);
public release<T extends Component>(obj: T | Node) {
if (obj instanceof Node) {
obj.active = false;
const index = this._actives.indexOf(obj);
this._actives.splice(index, 1);
this._inactives.push(obj);
} else {
obj.node.active = false;
const index = this._actives.indexOf(obj.node);
this._actives.splice(index, 1);
this._inactives.push(obj.node);
public release(obj: Node): void;
public release<T extends Component>(obj: T): void;
public release<T extends Component>(obj: T | Node): void {
let node = obj instanceof Node ? obj : obj.node;
const index = this._actives.indexOf(node);
//check obj is belongs to pool
if (index === -1) return;
this._actives.splice(index, 1);
this._inactives.push(node);
// Invoke pool handler
const handler = this._poolHandlerComp ? node.getComponent(this._poolHandlerComp) : null;
if (handler) {
(handler as unknown as IPoolable)?.unuse();
}
// Remove from parent, but don't cleanup
node.removeFromParent();
}
public clear() {