求解:cocos creator 3d 怎么使用对象池

比如在射击游戏中,子弹发射出去后过几秒就没有用了,我想利用对象池来回收,重复使用这一颗子弹

可以使用对象池
https://docs.cocos.com/creator3d/api/zh/classes/memop.pool.html

/**

  • @module 要用到节点池的脚本可继承此脚本
  • */
    import data_control from “…/lib/data_control”;

let {ccclass, property} = cc._decorator;

//来自节点池的属性
export class Pool_property {
id: string;
pos: number;
other: any;

//ID位置
constructor(id: string, pos: number) {
    this.id = id;
    this.pos = pos;
}

}

export class PoolNode extends cc.Node {
pool_property: Pool_property = null;
}

/*采用节点池复用节点/
@ccclass
class node_pool extends cc.Component {

@property({type: cc.Prefab, displayName: '复用预制', tooltip: ''})
prefab: cc.Prefab = null;

static Pool_property = typeof Pool_property;

//成员
private Pool: cc.NodePool = new cc.NodePool();
protected recordArray: Array<PoolNode> = [];

/**
 * @returns {PoolNode}
 */
newPoolNode(parent: cc.Node = null): PoolNode {
    let pool = null;
    let created = false;
    if (this.Pool.size() > 0) { // 通过 size 接口判断对象池中是否有空闲的对象
        pool = this.Pool.get();
        created = true;
    } else { // 如果没有空闲对象,也就是对象池中备用对象不够时,我们就用 cc.instantiate 重新创建
        pool = cc.instantiate(this.prefab);
    }
    const id = data_control.getRandId();
    // const id = Symbol();
    const pos = this.recordArray.length;
    pool.pool_property = new Pool_property(id, pos);
    this.recordArray.push(pool);
    if (parent) {
        parent.addChild(pool);
        if (created && pool.getComponent) {
            let com = pool.getComponent(cc.Component);
            com.onLoad && com.onLoad();
            com.start && com.start();
        }
    }
    return pool;
}

/**
 * @return PoolNode
 * */
getNodeOfId(id: string): PoolNode {
    for (let node of this.getAllNodes()) {
        if (node.pool_property.id == id) {
            return node;
        }
    }
    return null;
}

getNodeOfPos(pos: number): PoolNode {
    return this.recordArray[pos];
}

getAllNodes(): Array<PoolNode> {
    return this.recordArray;
}

deletePoolNode(node: PoolNode | cc.Node) {
    //
    if (node['pool_property']) {
        //坐标左移
        for (let i = node['pool_property'].pos + 1; i < this.recordArray.length; i++) {
            this.recordArray[i]['pool_property'].pos--;
        }
        this.recordArray.splice(node['pool_property'].pos, 1);
        node['pool_property'] = null;
        this.Pool.put(node);
    } else {
        console.error('删除出错', node);
    }
}

//此函数在切场景前会调用,从之前的记录里把所有节点收回到节点池
deleteAllPool() {
    while (this.recordArray.length > 0) {
        this.deletePoolNode(this.recordArray[0]);
    }
}

//将所有节点收回后再销毁池内所有对象
destroyAll() {
    //这里调不调都无所谓,切换场景前已经调用过
    this.deleteAllPool();
    //
    while (this.Pool.size()) {
        let node = this.Pool.get();
        node.destroy();
    }
}

onDestroy() {
    //是否销毁 ?
    this.destroyAll();
}

}

export default node_pool;

node_pool.zip (1.5 KB)

好的,感谢!

谢谢大佬的帮助