feat: update object pooling
parent
1912f52b83
commit
4d97fc35ea
|
@ -962,6 +962,12 @@
|
|||
"__prefab": {
|
||||
"__id__": 70
|
||||
},
|
||||
"rigidbody": {
|
||||
"__id__": 67
|
||||
},
|
||||
"collider": {
|
||||
"__id__": 65
|
||||
},
|
||||
"_id": ""
|
||||
},
|
||||
{
|
||||
|
|
|
@ -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');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export default interface IPoolable {
|
||||
unuse(): void;
|
||||
reuse(): void;
|
||||
reuse();
|
||||
unuse();
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
|
|
Loading…
Reference in New Issue