美文网首页
游戏框架与组件(1):对象池

游戏框架与组件(1):对象池

作者: 小木沐木 | 来源:发表于2021-02-01 14:53 被阅读0次

本文介绍了对象池以及对象池的代码实现。

本文链接  游戏框架与组件(1):对象池

一、为什么需要对象池

        对象池和内存池类似。都是为了解决对象创建、销毁和复用的问题。

        内存池中,频繁new申请内存,会造成两个问题。

        (1)new操作很耗性能

        (2)频繁申请的内存块,造成大量内存碎片

        所以内存池就是用来解决这个问题的。内存池至少提供了两个机制

        (1)根据算法将预先申请好的大内存块,分成很多个级别的小内存块供程序申请。

        (2)优先复用已回收的、合适的对象

        以上机制解决了new操作和内存碎片的问题。

        对象池和内存池类似。主要解决频繁新建和销毁对象性能消耗及对象复用的问题。

二、对象池设计

        实现对象池需要解决以下几个问题。

        1、对象池管理器。管理器的新建、销毁问题。新增对象池、销毁对象池接口

        2、对象池。对象池新建、销毁、新增某类对象合、销毁某类对象集合

        3、池对象类。继承于池对象类的对象,自身拥有从池中创建、回收到池中的接口。受对象池管理。

        4、未继承于池对象类的对象,则有对象池来显示进行新建和回收操作。

        图示(1/2)如下:

对象池及管理器

    图示(2/2)如下,UML类图关系。

对象池UML类图

三、对象池实现

        我们以TypeScript语言为例来实现对象池。

        1、我们先实现ObjectPool对象池类。

export class ObjectPool<T> {

    public static NAME: string = "ObjectPool";

    /** 存储表 */

    private pool: HashTable<T[]> = null;

    constructor() {

        this.pool = new HashTable<T[]>();

    }

    /** 

     * 回收对象接口

     * @param object 对象

     * @param key 对象标识

     * @param recoverHandler 激活时需要执行的回调

     * @param limitCount 池中允许缓存的最大数量

     * @param recoverHandler 池中对象满时的回调

     */

    public pushObject(object: T, key: string | number, recoverHandler?: Function, limitCount: number = 0, limitHandler?: Function): void {

        if (!object || this.isInPool(object)) {

            logger.error(this, "对象为空或已存在于内存池中, 回收失败", object, key);

            return;

        }

        if (!key) {

            logger.error(this, "对象的key为空, 回收失败", object, key);

        }else {

            let objList = this.pool.get(key);

            if (!objList) {

                objList = [];

                this.pool.insert(key, objList);

            }

            if (limitCount == 0 || objList.length < limitCount) {

                objList.push(object);

            }else {

                if (limitHandler) {

                    if (typeof limitHandler == "function") {

                        limitHandler(object);

                    }

                }

                return;

            }

            object["__is_in_pool"] = true;

            let recoverFunc = object["onRecoverToPool"];

            if (recoverFunc && typeof recoverFunc == "function") {

                (recoverFunc as Function).bind(object)();

            }

            if (recoverHandler) {

                if (typeof recoverHandler == "function") {

                    recoverHandler(object);

                }

            }

        }

    }

    /** 

     * 获取池对象接口

     * @param key 对象标识

     * @param createFunction 创建函数

     * @param awakeHandler 池中对象被取出激活时,需要处理的回调

     * @param ...args 对象构造函数需要传的参数

     */

    public getObject(key: string | number, createFunction?: Function, awakeHandler?: (poolObject: any) => void, ...args): T {

        let retObj: T = null;

        if (this.size(key) > 0) {

            if (key) {

                let objList = this.pool.get(key);

                if (objList) {

                    if (objList.length > 0) {

                        retObj = objList.pop();

                        if (objList.length == 0) {

                            // 删除数据

                            this.pool.delete(key);

                        }

                    }

                }

            }else {

                logger.error(this, "获取对象的key不能为空");

                return;

            }

        }

        if (!retObj && createFunction) {

            let newObject = createFunction() as T;

            retObj = newObject;

        }

        if (retObj) {

            if (retObj["__is_in_pool"] == false) {

                logger.error(this, "获取的对象状态错误!", retObj);

            }

            retObj["__is_in_pool"] = false;

            let awakeFunc = retObj["onAwakeFromPool"];

            if (awakeFunc && typeof awakeFunc == "function") {

                (awakeFunc as Function).bind(retObj)();

            }

            if (awakeHandler) {

                if (typeof awakeHandler == "function") {

                    retObj && awakeHandler(retObj);

                }

            }

        }

        return retObj;

    }

    /** 

     * 删除对象

     */

    public removeObject(removeObj: T, key: string | number, destroyFunc?: Function): void {

        let objs = this.pool.get(key);

        if (objs && objs.length > 0) {

            for (let i = 0; i < objs.length; i++) {

                const obj = objs[i];

                if (obj == removeObj) {

                    objs.splice(i, 1);

                    if (destroyFunc) {

                        destroyFunc(removeObj);

                    }

                    return;

                }

            }

        }

    }

    /** 

     * 查询池对象组接口

     * @param key 对象标识

     */

    public queryObjects(key: string | number): T[] {

        let retObjs: T[] = [];

        if (this.size(key) > 0) {

            if (key) {

                retObjs = this.pool.get(key) || retObjs;

            }else {

                logger.error(this, "获取对象的key不能为空");

            }

        }

        return retObjs;

    }

    /** 

     * 获取对象数量 

     * @param key 对象标识

     */

    public size(key: string | number): number {

        let objList = this.pool.get(key);

        if (objList) {

            return objList.length;

        }

        return 0;

    }

    /** 

     * 获取所有对象数组

     * @param key 对象标识

     */

    public asArray(key?: string | number): T[] {

        if (key) {

            return this.pool.get(key) || [];

        }else {

            let size = this.pool.size();

            if (size > 0) {

                let ret = [];

                this.pool.foreach2(function(_key: string, obj: T) {

                    let subObjs = this.pool.get(_key) || [];

                    for (let i = 0; i < subObjs.length; i++) {

                        ret.push(subObjs[i]);

                    }

                }.bind(this));

                return ret;

            }

        }

        return [];

    }

    /** 是否在对象池中 */

    public isInPool(object: T): boolean {

        if (!object) {

            return false;

        }

        return !!object["__is_in_pool"];

    }

    /** 获取所有key列表 */

    keys() {

        return this.pool.keys();

    }

}

        2、实现对象池管理类ObjectPoolManager

export class ObjectPoolMgr {

    /** 单例对象 */

    private static __instance: ObjectPoolMgr = null;

    /** 对象池类型表 */

    private poolTypeTable: HashTable<ObjectPool<any>> = null;

    private constructor() {

        this.poolTypeTable = new HashTable<ObjectPool<any>>();

    }

    public static getInstance() {

        if (!ObjectPoolMgr.__instance) {

            ObjectPoolMgr.__instance = new ObjectPoolMgr();

        }

        return ObjectPoolMgr.__instance;

    }

    /** 

     * 创建一个对象池

     * 

     */

    protected createPool<T>(key: string, creator?: Function): ObjectPool<T> {

        let newPool = creator ? creator() : new ObjectPool<T>();

        this.poolTypeTable.insert(key, newPool);

        return newPool;

    }

    /** 

     * 获取一个对象池

     * 

     */

    public static getPool<T>(key?: string, creator?: Function): ObjectPool<T> {

        let pool = ObjectPoolMgr.getInstance().poolTypeTable.get(key);

        if (!pool) {

            pool = ObjectPoolMgr.getInstance().createPool<T>(key, creator);

        }

        return pool;

    }

    /** 销毁对象池 */

    public removePool(key: string): void {

    }

    /** 获取对象数量 */

    public size(): number {

        return this.poolTypeTable.size();

    }

}

        3、池对象类PoolObject

export class PoolObject extends HashCode {

    public static NAME:string = "PoolObject";

    public static _poolKey: string = PoolObject.NAME;

    public static _pool: any = ObjectPoolMgr.getPool(PoolObject._poolKey);

    public static _classRefCache = {};

    public static _objectMap: {key?: [number]} = {};

    public static _objectIDMap: {key?: [number]} = {};

    constructor() {

        super();

    }

    /**

     * 获取是否在对象池中

     */

    public isInPool(): boolean {

        return PoolObject._pool.isInPool(this);

    }

    /**

     * 获取对象

     * @param classRef 类

     * @param createFunction 自定义创建函数,返回对象

     * @param awakeHandler 池中对象被取出激活时,需要处理的回调

     * @param ...args 对象构造函数需要传的参数

     */

    public static createFromPool<T>(classRef: new (...args: any[]) => T, createFunction?: (...args: any[]) => T, awakeHandler?: (poolObject: T) => void, disableReConstructor: boolean = false, ...args): T {

        let key = getFunctionId(classRef);

        let createFunc = createFunction;

        if (createFunction) {

            createFunc = () => {

                let newObj = createFunction(...args);

                let objFid = getFunctionId(newObj.constructor);

                PoolObject._objectIDMap[objFid] = key;

                PoolObject._objectMap[key] = (PoolObject._objectMap[key] || 0) + 1;

                return newObj;

            };

        }else {

            createFunc = () => {

                let newObj = new classRef(...args);

                let objFid = getFunctionId(newObj.constructor);

                PoolObject._objectIDMap[objFid] = key;

                PoolObject._objectMap[key] = (PoolObject._objectMap[key] || 0) + 1;

                return newObj;

            };

        }

        let _awakeHandler = (poolObj: T) => {

            if (!disableReConstructor) {

                poolObj.constructor(...args);

            }

            awakeHandler && awakeHandler(poolObj);

        }

        return PoolObject._pool.getObject(key, createFunc, _awakeHandler, ...args);

    }

    /**

     * 回收对象

     */

    public recoverToPool(recoverHandler?: Function): void {

        if (this.isInPool()) {

            return;

        }

        let objFid = getFunctionId(this.constructor);

        let key = PoolObject._objectIDMap[objFid];

        PoolObject._pool.pushObject(this, key, recoverHandler);

    }

    /** 

     * 获取池中对象数量

     */

    public static getPoolObjectCount<T>(classRef: new (...args: any[]) => T): number {

        return (PoolObject._pool as ObjectPool<T>).size(getFunctionId(classRef));

    }

    /** 

     * 获取对象总数量

     */

    public static getObjectTotalCount<T>(classRef: new (...args: any[]) => T): number {

        let id = getFunctionId(classRef);

        return PoolObject._objectMap[id] || 0;

    }

}

本文链接  游戏框架与组件(1):对象池

相关文章

  • 游戏框架与组件(1):对象池

    本文介绍了对象池以及对象池的代码实现。 本文链接游戏框架与组件(1):对象池[https://www.jiansh...

  • 面向对象编程套路

    1、对象池2、数据缓存对象3、管道4、事件队列与消息循环熟悉对象之间的协作与三种消息交换方式在开发框架中寻找上述套...

  • [个人框架 C_Framework] C_Pool快速对象池

    对象池 作为游戏开发过程中最常用的手段之一,在C_Framework框架中也必然会有,那么什么是池呢,池实际上可以...

  • 游戏 对象池

    代码实现

  • 刚体组件-Rigidbody

    刚体组件为游戏对象提供了物理属性,让游戏对象在场景中可以受到物理引擎的作用。当游戏对象添加了Rigidbody组件...

  • unity游戏对象,组件,Prefabs

    创建游戏对象和组件 任何游戏对象都是由组件组成,不同的组件有不同的功能,不同组件之间的互相组合以及组件属性之间的差...

  • 对象池优化内存

    对象池优化内存 1. 对象池优化是游戏开发中非常重要的优化方式,也是影响游戏性能的重要因素之一2. 游戏中有许多对...

  • Unity_简单对象池的运用

    一、脚本1:对象池:用于存放相同类型的游戏对象 usingSystem.Collections; usingSys...

  • 微信小游戏性能优化点

    1. 对象池 多数游戏,频繁创建和销毁同类对象很常见,使用对象池已是基本操作,必须牢记并熟练使用。推荐一个应用示例...

  • Unity 游戏框架搭建 (十九) 简易对象池

    在Unity中我们经常会用到对象池,使用对象池无非就是解决两个问题: 一是减少new时候寻址造成的消耗,该消耗的原...

网友评论

      本文标题:游戏框架与组件(1):对象池

      本文链接:https://www.haomeiwen.com/subject/vpoxtltx.html