关于对象池的一些代码

来源:互联网 发布:mac无法安装pkg 编辑:程序博客网 时间:2024/06/05 17:48

对象池的概念大概就是把不需要使用的物体设置成未激活,然后在需要使用时把他激活出来,而不是Destroy这个物体。原因是GC(垃圾回收)的内存消耗。这次不做介绍,以后可能会详细说明一些关于GC的内容,这里只介绍对象池。

对象池的使用地方:一些频繁生成物体的地方,具体是调用GameObject.Instantiate这个函数的时候,如果数量很多,那么使用对象池可以很好的优化整个项目。

那么就可以引申出创建的这个物体需要有什么属性方法了,我们可以定义一个接口:


// 表示可回收利用
public  interface  IReusable {
    // 卵生物体
    void Spawn();
    // 回收物体
    void UnSpawn();

}

需要实现这个接口的意义就是在卵生物体和回收物体时,去调用各自的方法,内容是对物体的一些操作,可以是位置、缩放、旋转等属性,具体看情况。

接下来我们就可以实现对象池的脚本了:

public class SubPool : MonoBehaviour {


    List<GameObject> m_pool = new List<GameObject>();
    //预设体引用
    GameObject m_Prefab;
    public string Name
    {
        get
        {
            return m_Prefab.name;
        }
    }

    public SubPool (GameObject prefab)
    {
        m_Prefab = prefab;
    }
    public GameObject Spwan()
    {
        GameObject obj = null ;
        foreach (GameObject  item in m_pool)
        {
            if (!item.activeSelf)
            {
                obj = item;
                break;
            }
        }
        if (obj == null)
        {
            obj = GameObject.Instantiate(m_Prefab);
            m_pool.Add(obj);
        }
        obj.SetActive(true);
        //执行物体卵生后的方法
        IReusable reusable = obj.GetComponent<IReusable>();
        if (reusable != null)
        {
            reusable.Spawn();
        }
        return obj;
    }


    public void UnSpwan(GameObject unSpwanObj)
    {
        if (m_pool.Contains(unSpwanObj))
        {           
            IReusable reusable = unSpwanObj.GetComponent<IReusable>();
            if (reusable != null)
            {
                reusable.UnSpawn();
            }
            unSpwanObj.SetActive(false);
        }
    }
    /// <summary>
    /// 回收所有物体
    /// </summary>
    public void UnSpwanAll()
    {
        foreach (GameObject item in m_pool)
        {
            if (item.activeSelf)
            {
                
                IReusable reusable = item.GetComponent<IReusable>();
                if (reusable != null)
                {
                    reusable.UnSpawn();
                }
                item.SetActive(false);
            }
               
        }
    }

}

以上的脚本大体的意思是用一个List集合去保存可回收的对象,如果List中没有可用对象,那么就创建一个新的对象,如果有可用对象,那么把他卵生出来,并调用卵生的方法,最后移除出List集合。那么当需要销毁对象时,把他设置成未激活状态,加入List集合,可以下次继续使用,并调用回收方法。还有一个回收所有的方法,不详细描述。


以上就是对象池的代码,可能和别人的有什么差别,但是思想应该差不多。

根据以上的代码,我们可以写一个Controller去管理一个个对象池,这个Controller用的地方在你有很多对象池,代码如下:

/// <summary>
/// 对象池控制器
/// </summary>
public class ObjectPoolController : MonoSingleton<ObjectPoolController> {


    private Dictionary<string, SubPool> m_pools = new Dictionary<string, SubPool>();

    public GameObject Spwan(string name)
    {
        //查找对象池
        SubPool pool;
        if (!m_pools.ContainsKey(name))
        {
            RegisterSubPool(name);         
        }
        //取出对应的对象池,并调用Spwan方法
        pool = m_pools[name];
        return pool.Spwan();
    }
    //注册一个对象池
    public void RegisterSubPool(string name)
    {
        GameObject prefab = Resources.Load<GameObject>(name);
        SubPool pool = new SubPool(prefab);
        m_pools.Add(pool.Name, pool);
    }

}

这个东西没什么难度,就是再次封装了一下对象池。大体就是把一个个的对象池注册到这个Controller中,在调用时查找相对应的对象池,取出并调用卵生方法。可以写的更好更方便一些,但是自己没用到也懒得写,意思一下。


0 1
原创粉丝点击