对象池的实现

对象池的作用:

        避免对象反复实例化,造成性能的下降。

代码设计:

        设计思路:

        对象池,这个对象既可以是gameobject,也可以是class,甚至是其他的东西,所以需要利用到c#的泛型这个语法,并且需要一个基类PoolBase<T>,这个基类为抽象类,需要父类继承基类并且重写基类的方法。基类中需要包括三个关键的方法,分别是创建对象、把对象从池子中获取出来、把对象回收到池子里。这样能够有效的避免对象实例化,更有效的提高游戏运行时的性能。

        除了对象池本身,还需要一个简单的管理器PoolManager去管理多个对象池,包括对象池的创建,获取指定对象池等方法。

        设计模式:

        PoolManager,单例模式,唯一实例,唯一控制。

        

        数据结构:

        PoolBase,可以使用栈或队列等结构存储对象,只要是获取任意对象的时间复杂度为O(1)的结构都可以。本人使用的是栈结构。

        PoolManager,使用字典存储对象池, 能够快速匹配查找即可。

        导图:

      

关键代码:

       PoolBase.cs

public abstract class PoolBase<T>
{
}

        对于不同的对象池来说,实例化对象的方式千差万别,所以把创建对象的方法设置为抽象函数。

public abstract T Create();

        从池子中获取对象,直接获取栈顶对象,没有的话自动创建一个新的对象。

    public virtual T Spawn()
    {
        if (_pool.Count > 0)
        {
            return _pool.Pop();
        }
        else
        {
            return Create();
        }
    }

        把对象回收至池子,把对象入栈即可。不过需要考虑池子满了的情况,无法回收至池子的对象需要交由派生类自己处理。

    public virtual bool Recycle(T obj)
    {
        if (obj == null)
        {
            return false;
        }
        if (_pool.Count >= _maxPoolCount)
        {
            return false;
        }
        _pool.Push(obj);
        return true;
    }

        清空对象池

    public virtual void ClearPool()
    {
        _pool.Clear();
    }

        PoolManager.cs

public class PoolManager 
{
}

        对对象池实例化,并且缓存至字典中,这里简单以GameObjectPool和ClassPool为例子。

    private Dictionary<string, object> _poolDict = new Dictionary<string, object>();

    public object CreateGameObjectPool(string name, string path, int maxPoolCount)
    {
        object pool = null;
        if (_poolDict.TryGetValue(name, out pool) == false || pool == null)
        {
            GameObjectPool newPool = new GameObjectPool(path, maxPoolCount);
            _poolDict.Add(name, newPool);
            return newPool;
        }
        return pool;
    }


    public object CreateClassPool<T>(string name, int maxPoolCount) where T : class, new()
    {
        object pool = null;
        if (_poolDict.TryGetValue(name, out pool) == false || pool == null)
        {
            ClassPool<T> newPool = new ClassPool<T>(maxPoolCount);
            _poolDict.Add(name, newPool);
        }
        return pool;
    }


    public object GetPool(string name)
    {
        object pool = null;
        _poolDict.TryGetValue(name, out pool);
        return pool;
    }

        GameObjectPool.cs

        为PoolBase的派生类,只需要关注GameObject的特性即可。

public class GameObjectPool : PoolBase<GameObject>
{
}

        创建gameobject对象。

    public override GameObject Create()
    {
        GameObject obj = GameObject.Instantiate(Resources.Load(_path)) as GameObject;
        //GameObject prefab = AssetsLoad.LoadAssets<GameObject>(_path);
        GameObject obj = GameObject.Instantiate(prefab);
        obj.SetActive(true);
        return obj;
    }

        从池子中获取gameobject对象,需要setactive。

    public override GameObject Spawn()
    {
        GameObject obj = base.Spawn();
        obj.SetActive(true);
        return obj;
    }

       

        把gameobject对象回收至池子,回收失败需要销毁gameobject对象

    public override bool Recycle(GameObject obj)
    {
        if (obj == null)
        {
            return false;
        }
        bool isSuccess = base.Recycle(obj);
        if (isSuccess == false)
        {
            GameObject.Destroy(obj);
        }
        else
        {
            obj.transform.SetParent(_poolRoot);
        }
        return isSuccess;
    }

        ClassPool.cs

        跟GameObjectPool同理,只需要关注自身特性即可。

public class ClassPool<T> : PoolBase<T> where T : class, new()
{
}

        拓展:

        可以根据实际的需求,添加其他方法,如批量从池子中获取对象或者批量回收对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值