Unity基础小框架(二):对象池(缓存池)模块

9 篇文章 0 订阅
6 篇文章 0 订阅

使用对象池能够重复利用创建的资源,避免重复的创建和销毁,减少内存分配和垃圾回收带来的开销。当某个物品需要重复的创建和销毁时,就可以考虑用到对象池。

核心需要两样

  1. 存放不同对象池的一个容器,Dictionary
  2. 存放物体的对象池,List、Stack、Queue等等

是否设置构造函数为私有取决于继承的单例模板的实现方式,使用单例模式是为了确保该类具有唯一的实例,并能够通过获取实例的方法直接调用对象池模块里的内容。

在存取对象时,是否激活或者隐藏物体取决于具体的设计,还可以采用将物体移动到某个位置等方法。

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

public class PoolData
{
    public GameObject father;
    public Stack<GameObject> poolStack;

    public PoolData(GameObject obj, GameObject poolFather)
    {
        father = new GameObject(obj.name);
        father.transform.parent = poolFather.transform;
        poolStack = new Stack<GameObject>();
        PushObj(obj);
    }

    public void PushObj(GameObject obj)
    {
        obj.SetActive(false);
        poolStack.Push(obj);
        obj.transform.SetParent(father.transform);
    }

    public GameObject GetObj()
    {
        GameObject obj = poolStack.Pop();
        obj.SetActive(true);
        obj.transform.parent = null;
        return obj;
    }
}


public class PoolManager : BaseManger<PoolManager>
{
    //作为储存不同类型对象池的容器
    private Dictionary<string, PoolData> poolDic = new Dictionary<string, PoolData>();
    private PoolManager() { }

    private GameObject poolObj;
    /// <summary>
    /// 获取一个物体
    /// </summary>
    /// <param name="name"></param>
    /// <returns></returns>
    public GameObject GetObj(string name)
    {
        GameObject obj = null;
        try
        {
            //判断该类型池是否存在,并且池中是否有物体
            if (poolDic.ContainsKey(name) && poolDic[name].poolStack.Count > 0)
            {
                obj = poolDic[name].GetObj();
            }
            else
            {
                //不存在就直接从资源里加载并在场景生成一个物体
                obj = Instantiate(Resources.Load<GameObject>(name));
                obj.name = name;    //去掉(clone)后缀
            }
        }
        catch(Exception e)
        {
            Debug.LogError("资源获取失败:" + e.Message);
        }
        return obj;
    }

    /// <summary>
    /// 将物体放入对象池
    /// </summary>
    /// <param name="name"></param>
    /// <param name="obj"></param>
    public void PushObj(string name, GameObject obj)
    {
        if (poolObj is null)
        {
            poolObj = new GameObject("Pool");
        }

        if (poolDic.ContainsKey(name))
        {
            poolDic[name].PushObj(obj);
        }
        else
        {
            poolDic.Add(name, new PoolData(obj, poolObj));
        }
    }

    /// <summary>
    /// 清空全部池
    /// </summary>
    public void ClearAllPool()
    {
        poolDic.Clear();
        poolObj = null;
    }
}

如果想要异步加载资源,则做如下修改

资源管理器模块

    public void GetObj(string name, UnityAction<GameObject> callback)
    {
        try
        {
            //判断该类型池是否存在,并且池中是否有物体
            if (poolDic.ContainsKey(name) && poolDic[name].poolStack.Count > 0)
            {
                callback(poolDic[name].GetObj());
            }
            else
            {
                ResManager.GetInstance().LoadAsync<GameObject>(name, callback);
            }
        }
        catch(Exception e)
        {
            Debug.LogError("资源获取失败:" + e.Message);
        }        
    }

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值