【Unity】基础缓存池

缓存池需求
1.有一个公共存储空间
2.当我们需要一个对象时从这个公共空间去获取。
若空间中有想要的对象,直接返回使用。
若空间中没有想要的对象,就去创建一个需要的对象并返回。
3.当对象使用完毕时不删除,而是放入这个公共空间待下次使用。


缓存池的作用
将频繁使用的对象放入缓存池,可以节约cup开销,但是会有内存开销。用内存换cpu性能的典型表现。一般子弹,特效等相关对象会使用缓存池。

原理
在这里插入图片描述
制作思路
缓存池是一个管理者角色(单例模式)
缓存池可以作为多种对象容器(Dictionary+List)
缓存池中可以取,可以放:
放入方法
取出方法

缓存池知识点
1.单例模式
2.Dictionary
3.List
4.GameObject.SetActive()
5.GameObject.Instantiate
6.Resources.load

代码

/// <summary>
/// 单例模式基类
/// </summary>
/// <typeparam name="T"></typeparam>
public class BaseManger<T> where T : new()

{
    private static T _instance;

    public static T instance
    {
        get
        {
            if (_instance == null)
            {
                _instance = new T();
            }
            return _instance;
        }

    }

}

/// <summary>
/// 缓存池模块
/// 1.Dictionary List
/// 2.Gameobject和Resources 两个公共类的API
/// </summary>
public class poolMgr:BaseManger<poolMgr> 
{
    //缓存池容器
    public Dictionary<string, List<GameObject>> poolDic = new Dictionary<string, List<GameObject>>();

    /// <summary>
    /// 往外拿东西 
    /// name是预设体的名字和路径
    /// </summary>
    /// <param name="name"></param>
    /// <returns></returns>
    public GameObject GetObj(string name)
    {
        GameObject obj = null;

        //缓存池里有gameobject
        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)
    {
        //放进去的时候让gameobject失活
        obj.SetActive(false);

        //里面有gameobject
        if (poolDic.ContainsKey(name))
        {
            poolDic[name].Add(obj);
        }
        //里面没有
        else
        {
            poolDic.Add(name, new List<GameObject>() { obj });
        }
    }
}

测试
写一个测试脚本,随便挂载空物体Gameobject上,鼠标摁下左键创建Cube,鼠标摁下右键创建Sphere。

public class PoolTest : MonoBehaviour
{
    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            poolMgr.instance.GetObj("Test/Cube");
        }
        if (Input.GetMouseButtonDown(1))
        {
            poolMgr.instance.GetObj("Test/Sphere");
        }
    }
}

在Resources/Test目录下创建Cube和Sphere的预设体
在这里插入图片描述


写一个延迟放入缓存池的脚本,挂载到Cube和Sphere上。

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

    // Update is called once per frame

    void push()
    {
        poolMgr.instance.PushObj(this.gameObject.name, this.gameObject);
    }
}

在这里插入图片描述
缺点:暴露在Hierarchy面板下,最好能放入一个父对象层级下。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值