unity 对象池

9 篇文章 0 订阅
2 篇文章 0 订阅


对象池背后的理念其实是非常简单的。我们将对象存储在一个池子中,当需要时在再次使用,而不是每次都实例化一个新的对象。池的最重要的特性,也就是对象池设计模式的本质是允许我们获取一个“新的”对象而不管它真的是一个新的对象还是循环使用的对象。

这是网上找的解释。
我们游戏中大量用到了对象池。
今天看了下对象池底层的代码。下面这篇文章写得挺好
废话不多说,上我们自己的对象池代码。

using System;
using UnityEngine;
using System.Collections;
using System.Collections.Generic;


// 清0操作由调用者负责编写
// 提供对非unity对象的缓存,即逻辑对象缓存
// 注意必须是class哈
// 提供接口 IObjectClear, Release时自动调用

public interface IObjectClear
{
    void Clear();
}

public class ObjectPool
{
    class ObjectGroup
    {
        public Stack<object> m_freeStack;
        public int m_iMaxNum;  // 最大数量,为0表示不限制,否则超过最大数量,Release时直接delete

        public ObjectGroup()
        {
            m_freeStack = new Stack<object>();
            m_iMaxNum = 0;
        }
    }
   
    Dictionary< Type,   ObjectGroup > m_typeDic;
    object m_locker = new object();
    bool m_bIsthreadSafe;

    public ObjectPool(bool bIsthreadSafe = false)
    {
        m_typeDic = new Dictionary< Type,   ObjectGroup >();
        m_bIsthreadSafe = bIsthreadSafe;
    }

    public void Register<T>( int iInitNum, int iMaxNum = 0 ) where T : class, new()
    {
        if (iInitNum < 0)
        {
            throw new ArgumentException("Init num < 0");
        }

        ObjectGroup group = null;
        if ( m_typeDic.TryGetValue(typeof(T), out group) )
        {
            // 已存在
            return;
        }

        group = new ObjectGroup();
        group.m_iMaxNum = iMaxNum;

        if (iInitNum > 0)
        {
            for (int i = 0; i < iInitNum; i++)
            {
                T obj = new T();
                if (m_bIsthreadSafe)
                {
                    lock (m_locker)
                    {
                        group.m_freeStack.Push(obj);
                    }
                }
                else
                {
                    group.m_freeStack.Push(obj);
                }
            }
        }

        m_typeDic[typeof(T)] = group;
    }

    public T Get<T>() where T : class, new()
    {
        ObjectGroup group = null;
        if (!m_typeDic.TryGetValue(typeof(T), out group))
        {
            Register<T>(1);
            return Get<T>();
        }

        T obj = null;
        if (0 == group.m_freeStack.Count)
        {
            obj = new T();
        }else 
        {
            if (m_bIsthreadSafe)
            {
                lock (m_locker)
                {
                    obj = group.m_freeStack.Pop() as T;
                }
            }
            else
            {
                obj = group.m_freeStack.Pop() as T;
            }
        }

        return obj;
    }

    public void Release<T>(T obj) where T : class, new()
    {
        if (null == obj)
        {
            throw new ArgumentException("obj is null!!");
        }

        ObjectGroup group = null;
        Type t = ((object)obj).GetType();
        if (!m_typeDic.TryGetValue(t, out group))
        {
            throw new ArgumentException("obj's type is not registered!");
        }

        if (obj is IObjectClear)
        {
            ((IObjectClear)obj).Clear();
        }

        if (group.m_iMaxNum > 0 && group.m_freeStack.Count >= group.m_iMaxNum)
        {
            if (obj is IDisposable)
            {
                ((IDisposable)obj).Dispose(); 
            }

            obj = null;
            System.GC.Collect();
        }
        else
        {
            // add to free list
            if (m_bIsthreadSafe)
            {
                lock (m_locker)
                {
                    group.m_freeStack.Push(obj);
                }
            }
            else
            {
                group.m_freeStack.Push(obj);
            }
        }
    }

    private void _DestroyGroup( ObjectGroup group )
    {
        object obj = null;
        while (group.m_freeStack.Count > 0)
        {
            if (m_bIsthreadSafe)
            {
                lock (m_locker)
                {
                    obj = group.m_freeStack.Pop();
                }
            }
            else
            {
                obj = group.m_freeStack.Pop();
            }

            if (obj is IDisposable)
            {
                ((IDisposable)obj).Dispose();
            }
            obj = null;
        }
        if (m_bIsthreadSafe)
        {
            lock (m_locker)
            {
                group.m_freeStack.Clear();
            }
        }
        else
        {
            group.m_freeStack.Clear();
        }
    }

    public void DestroyType<T>() where T : class, new()
    {
        ObjectGroup group = null;
        if (!m_typeDic.TryGetValue(typeof(T), out group))
        {
            throw new ArgumentException("obj's type is not registered!");
        }

        this._DestroyGroup(group);
    }

    // destroy所有实列
    public void DestroyAll()
    {
        foreach (var it in m_typeDic)
        {
            ObjectGroup group = it.Value;
            this._DestroyGroup(group);
            group = null;
        }

        m_typeDic.Clear();
       
        System.GC.Collect();
    }
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值