Unity中对象池的应用ObjectPool
2023-09-27 14:27:15 时间
用来理解对象池的简单示例使用了 https://blog.csdn.net/A13155283231/article/details/92098649 中的例子
ObjcetPool用来新建和回收游戏里的对象
public class ObjectPool
{
private Queue<GameObject> m_PoolQueue;
private string m_PoolName;
protected Transform m_Parent;
// 需要缓存的对象
private GameObject prefab;
// 最大容量
private int m_MaxCount;
protected const int m_DefaultMaxCount = 10;
public GameObject Prefab { get => prefab; set => prefab = value; }
public ObjectPool()
{
m_MaxCount = m_DefaultMaxCount;
m_PoolQueue = new Queue<GameObject>();
}
public virtual void Init(string poolName, Transform transform)
{
m_PoolName = poolName;
m_Parent = transform;
}
public virtual GameObject Get(Vector3 pos, float lifetime)
{
if (lifetime < 0)
{
return null;
}
GameObject returnObj;
if (m_PoolQueue.Count > 0)
{
returnObj = m_PoolQueue.Dequeue();
}
else
{
// 池中没有可分配对象了,新生成一个
returnObj = GameObject.Instantiate<GameObject>(prefab);
returnObj.transform.SetParent(m_Parent);
returnObj.SetActive(false);
}
// 使用PrefabInfo脚本保存returnObj的一些信息
ObjectInfo info = returnObj.GetComponent<ObjectInfo>();
if (info == null)
{
info = returnObj.AddComponent<ObjectInfo>();
}
info.PoolName = m_PoolName;
if (lifetime > 0)
{
info.Lifetime = lifetime;
}
returnObj.transform.position = pos;
returnObj.SetActive(true);
return returnObj;
}
// "销毁对象" 其实是回收对象
public virtual void Recycle(GameObject obj)
{
if (m_PoolQueue.Contains(obj))
{
return;
}
if (m_PoolQueue.Count > m_MaxCount)
{
// 对象池已满 直接销毁
GameObject.Destroy(obj);
}
else
{
// 放入对象池
m_PoolQueue.Enqueue(obj);
obj.SetActive(false);
}
}
public virtual void Destroy()
{
m_PoolQueue.Clear();
}
}
上面代码主要理解下从池中取出对象后,要从池中移除该对象
因为对象使用结束后会回到池中
CubePool.cs
public class CubePool : ObjectPool
{
public override GameObject Get(Vector3 pos, float lifetime)
{
GameObject obj;
obj = base.Get(pos, lifetime);
obj.GetComponent<Renderer>().material.color = Random.ColorHSV();
return obj;
}
}
ObjcetInfo.cs 用来记录对象信息 并且 定时回收对象
public class ObjectInfo : MonoBehaviour
{
public float Lifetime = 0;
public string PoolName;
private WaitForSeconds m_WaitTime;
private void Awake()
{
if (Lifetime > 0)
{
m_WaitTime = new WaitForSeconds(Lifetime);
}
}
private void OnEnable()
{
if (Lifetime > 0)
{
StartCoroutine(CountDown(Lifetime));
}
}
IEnumerator CountDown(float lifetime)
{
yield return m_WaitTime;
ObjectPoolManager.Instance.RemoveGameObject(PoolName, gameObject);
}
}
ObjcetPoolManager 用来管理多个对象池
public class ObjectPoolManager : Singleton<ObjectPoolManager>
{
private Dictionary<string, ObjectPool> m_PoolDic;
private Transform m_RootPoolTrans;
public ObjectPoolManager()
{
m_PoolDic = new Dictionary<string, ObjectPool>();
// 根对象池
GameObject go = new GameObject("ObjcetPoolManager");
m_RootPoolTrans = go.transform;
}
// 创建一个新的对象池
public T CreateObjectPool<T>(string poolName) where T : ObjectPool, new()
{
if (m_PoolDic.ContainsKey(poolName))
{
return m_PoolDic[poolName] as T;
}
GameObject obj = new GameObject(poolName);
obj.transform.SetParent(m_RootPoolTrans);
T pool = new T();
pool.Init(poolName, obj.transform);
m_PoolDic.Add(poolName, pool);
return pool;
}
public GameObject GetGameObject(string poolName, Vector3 position, float lifetTime)
{
if (m_PoolDic.ContainsKey(poolName))
{
return m_PoolDic[poolName].Get(position, lifetTime);
}
return null;
}
public void RemoveGameObject(string poolName, GameObject go)
{
if (m_PoolDic.ContainsKey(poolName))
{
m_PoolDic[poolName].Remove(go);
}
}
// 销毁所有对象池
public void Destroy()
{
m_PoolDic.Clear();javascript:void(0)
GameObject.Destroy(m_RootPoolTrans);
}
}
当然回收到对象池后可以进行属性重设的,不同种类的对象池可以重写这个方法重设不同的属性。比如
public virtual void Recycle(GameObject obj){
//待分配对象已经在对象池中
if(queue.Contains(obj)){
Debug.LogWarning("the obj " + obj.name + " be recycle twice!" );
return;
}
if( _freeObjCount > preAllocCount + autoIncreaseCount ){
Destroy(obj);//当前池中object数量已满,直接销毁
}else{
queue.Enqueue(obj);//入队,并进行reset
obj.transform.parent = this.transform;
obj.SetActive(false);
_freeObjCount++;
}
}
扩展学习Unity对象池的管理
ObjectPoolContainer 对象容器
ObjectPool 单一对象池
PoolManager 对象池管理
相关文章
- console.log的一个应用 -----用new方法生成一个img对象和document.createElement方法创建一个img对象的区别
- CV-图像分割-20230405:SAM(Segment Anything Model)【零样本分割图像中一切对象】【可应用于各种领域(目标检测、图像分类、物体分割),用于查找和分割图像中的任何对象】
- NLP-文本匹配-2013:DSSM【首次提出将深度学习应用到文本匹配,每个文本对象均由5层的神经网络进行向量化表示,最后通过向量间的余弦值来衡量文本对象的相似度】【釆用词袋模型,丢失单词顺序关系】
- 推荐系统:深度学习在推荐系统中的应用
- 云应用程序很慢?原因在应用,而不是云
- 【转】 Key/Value之王Memcached初探:三、Memcached解决Session的分布式存储场景的应用
- [转]HSPICE软件的应用及常见问题解决
- 思科ACI向企业网络扩展 引入APIC应用策略基础设施控制器
- HTML:图片超链接应用
- 大数据应用于人力 预测性劳动力分析真的有用么?
- 在Spring应用中创建全局获取ApplicationContext对象
- Oracle442个应用场景----------数据库逻辑对象管理
- 让Android模拟器速度飞起来_Eclipse+BlueStacks调试Android应用【2012-10-30】
- 第一天:Java源码级实战速成(通过动手实战类、对象等,通过Spark和Hadoop案例代码和源码解析具体指知识的应用、深度详解匿名接口在Spark开发中的运用)
- Unity中对象池的应用ObjectPool
- Android应用内 代码截屏(获取View快照)和 禁止截屏
- 线段树详解(原理、实现与应用)
- 语言拖拽文件命令,拖放对象组件应用
- 【错误记录】SeeMusic 一直卡在主界面无法使用 ( 删除 C:Users用户名称AppDataLocalLowVisual Music Design 应用信息 )
- 【Android 进程保活】应用进程拉活 ( 系统 Service 机制拉活 | Service 组件 onStartCommand 方法分析 | 源码资源 )