[Unity内存优化]对象池

为什么用对象池?
作用:因为Mono内存在Unity中不能手动释放,当其内存超过上限时,会先触发GC释放没有用到的内存空间,如果还不够则会扩充。其容量一旦被撑大,项目所占的内存就会跟着增大。使用对象池可以减少对象创建,缓解内存压力。

对象池示意 这里通过一个栈存储对象
m_MaxCount 表示最大储存个数
m_NoRecycleNum 用来记录未归还的对象

public class ClassObjectPool<T> where T : class,new(){
    protected Stack<T> m_Pool = new Stack<T>();
    protected int m_MaxCount = 0;    //最大储存个数
    protected int m_NoRecycleNum = 0;//未归还的对象
	//构造函数时限制最大储存个数 并压入对象
    public ClassObjectPool(int max_count){
        m_MaxCount = max_count;
        for(int i = 0;i<max_count;i++){
            m_Pool.Push(new T());
        }
    }

    /// <summary>
    /// 从池中取对象
    /// </summary>
    /// <param name="create_if_pool_empty">如果池是空的则创建</param>
    /// <returns></returns>
    public T Spawn(bool create_if_pool_empty = true){
        if(m_Pool.Count > 0){
            T res = m_Pool.Pop();
            if(res == null){
                if(create_if_pool_empty){
                    res = new T();
                    m_NoRecycleNum++;
                }
            }
            if(res != null)
                m_NoRecycleNum++;
            return res;
        }
        else{
            if(create_if_pool_empty){
                m_NoRecycleNum++;
                return new T();
            }
        }
        return null;
    }

    /// <summary>
    /// 把对象放回池中
    /// </summary>
    /// <param name="obj">还回对象</param>
    /// <returns></returns>
	public bool Recycle(T obj){
        if(obj == null)
            return false;
        m_NoRecycleNum--;
        //如果池内对象已经达到最大值,则不放入池中
        if(m_MaxCount > 0 && m_Pool.Count >= m_MaxCount){
            obj = null;
            return false;
        }
        MethodInfo[] methods = obj.GetType().GetMethods();
       	foreach(MethodInfo info in methods){
            //如果对象拥有Reset()方法 则调用一下
            if(info.Name == "Reset"){
            	obj.GetType().InvokeMember("Reset",BindingFlags.InvokeMethod|BindingFlags.Default,null,obj,new object[]{});
            }
        }
        m_Pool.Push(obj);
        return true;
    }
}

将对象归还到对象池,如果对象的信息需要重置,则需要重置再归还。可以在对象中添加重置方法,我这里在归还的时候使用反射调用

public class AssetBundleItem{
    public AssetBundle assetBundle = null;
    public int refCount = 0;
    public void Reset(){
        assetBundle = null;
        refCount = 0;
    }

以上是对象池的基础代码,但是这样还是可以 new 出多个相同类型的 ClassObjectPool,所以我采用一个字典,将已创建的对象池缓存起来统一管理

//缓存ObjectManager创建的对象池
    protected Dictionary<Type, object> obj_dic = new Dictionary<Type, object>();

    //获得或者创建一个对象池
    //当有对象池的时候则直接取,没有的时候按count的数量创建
    public ClassObjectPool<T> GetOrCreteObject<T>(int count = 1) where T : class, new()
    {
        Type type = typeof(T);
        object out_obj = null;
        if (!obj_dic.TryGetValue(type, out out_obj))
        {
            ClassObjectPool<T> new_pool = new ClassObjectPool<T>(count);
            obj_dic.Add(type, new_pool);
            out_obj = new_pool;
        }
        return out_obj as ClassObjectPool<T>;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值