缓存池模块基础

缓存池模块基础

 

当我们利用c#代码实例化对象时,内存空间中就会开辟一个区域用于储存实例化相关的信息,即使当我们删除这个实例化对象后,也只是断开了对内存空间中对应区域的引用,并没有真正地释放内存空间。

C#的内存空间机制:

当所有可用的内存空间都被占用时,才会去释放那些已经不会再使用的区域,用于储存新的信息。我们把这一过程叫做GC。

由于每一次GC时,系统需要重新检测大量的信息来判断是否有用,并删除,所以会对CPU产生巨大的损耗。通常情况下,每一次GC都会伴随着一点点的卡顿。

所以为了避免这一情况的发生,就需要使用到缓存池

缓存池的作用:

缓存池就好比我们的工具箱,当我们第一次实例化某一对象时,就像制造某一个工具,这时就在内存空间开辟一个新区域。而当我们对这一实例化对象进行删除时,缓存池就会记录下这一实例化对象的信息,也就是将这个工具装进了工具箱,当我们需要再次实例化这一对象时,就不需要重新在内存空间里开辟新区域,而是直接在缓存池里找出内存空间之前的区域调用的就行了,也就是把工具从工具箱里取出来继续使用就行了。

好处:

从短期来讲,这样会使内存空间中总有几个区域是一直被占据的,有点浪费内存,但从长期来讲这样做可以极大地减缓内存空间填满的时间,加长了每一次GC的间隔时间,减少有限时间内卡顿的次数。


相关的例子代码

缓存池模块:

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

/// <summary>
/// 缓存池模块
/// </summary>
public class PoolMgr :BaseManager<PoolMgr>
{
   //缓存池容器(衣柜)
   public Dictionary<string, List<GameObject>> poolDic = new Dictionary<string, List<GameObject>>();

   /// <summary>
   /// 往抽屉拿东西
   /// </summary>
   /// <param name="name"></param>
   /// <returns></returns>
   public GameObject GetObj(string name)
  {
       GameObject obj = null;
       //有抽屉,并且抽屉里有东西
       if (poolDic.ContainsKey(name) && poolDic[name].Count > 0)
      {
           //从字典中取出,并移除
           obj = poolDic[name][0];
           poolDic[name].RemoveAt(0);
      }
       else
      {
           obj = GameObject.Instantiate(Resources.Load<GameObject>(name));
           //把对象的名字改的和池子名字相同
           obj.name = name;
      }
       //激活,让其显示
       obj.SetActive(true);
       return obj;
  }
   /// <summary>
   /// 暂时不用的东西给抽屉
   /// </summary>
   public void PushObj(string name,GameObject obj)
  {
       //失活,让其隐藏
       obj.SetActive(false);
       //里面有抽屉
       if (poolDic.ContainsKey(name))
      {
           poolDic[name].Add(obj);
      }
       //里面没有抽屉
       else
      {
           poolDic.Add(name, new List<GameObject> { obj });
      }
  }
}

生成,从缓存池中取出

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

public class Test : MonoBehaviour
{
   // Start is called before the first frame update
   void Start()
  {
       
  }

   // Update is called once per frame
   void Update()
  {
       if (Input.GetMouseButtonDown(0))
      {
           PoolMgr.GetInstance().GetObj("Cube");
      }
       if (Input.GetMouseButtonDown(1))
      {
           PoolMgr.GetInstance().GetObj("Sphere");
      }
  }
}

移出,放进缓存池

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

public class DelayPush : MonoBehaviour
{
   // 当对象激活时,会进入的生命周期函数
   void OnEnable()
  {
       Invoke("Push", 1);//延迟一秒调用函数
  }

   void Push()
  {
       //放回缓存池
       PoolMgr.GetInstance().PushObj(this.gameObject.name, this.gameObject);
  }
}

原文地址:https://www.cnblogs.com/wei1349/p/12771070.html