Unity开发中对象池设计与使用详解
创作时间:
作者:
@小白创作中心
Unity开发中对象池设计与使用详解
引用
CSDN
1.
https://blog.csdn.net/2301_79022588/article/details/146284488
在Unity开发中,对象池是一种常用的优化技术,用于管理游戏中的对象,避免频繁创建和销毁对象带来的性能开销。本文将详细介绍对象池的设计原理和具体实现方法,帮助开发者更好地理解和应用这一技术。
设计目的
为了避免频繁创建和销毁对象(例如 UI 元素、事件对象等)带来的内存分配和垃圾回收压力,可以使用对象池来管理对象来提高游戏的性能,避免游戏卡顿。
代码实现
public interface IRecycle
{
/// <summary>
/// 回池必须调用的接口
/// </summary>
public void OnRecycle();
/// <summary>
/// 初始化接口
/// </summary>
public void OnFetch();
}
public class CacheObjectMgr : Singleton<CacheObjectMgr>
{
private Dictionary<Type, Queue<IRecycle>> m_Gos;
protected override void OnInit()
{
base.OnInit();
m_Gos = new Dictionary<Type, Queue<IRecycle>>();
}
public T Fetch<T>() where T : class, IRecycle, new()
{
IRecycle obj = null;
Queue<IRecycle> pool = _GetPool(typeof(T));
if (pool.Count > 0)
{
obj = pool.Dequeue();
}
else
{
obj = new T();
}
obj.OnFetch();
return obj as T;
}
public void Recycle(IRecycle go)
{
if (go != null)
{
go.OnRecycle();
_GetPool(go.GetType()).Enqueue(go);
}
}
private Queue<IRecycle> _GetPool(Type type)
{
Queue<IRecycle> pool = null;
if (!m_Gos.TryGetValue(type, out pool))
{
pool = new Queue<IRecycle>();
m_Gos.Add(type, pool);
}
return pool;
}
}
代码分析
字典存储结构:使用
Type作为键,存储每种类型对应的对象池(队列)。这样不同类型的对象可以分开管理,且在回收和取用时无需强制转换。对象池的设计:每个队列中存储的都是
IRecycle类型的对象。由于 C# 支持接口的多态性,只要对象实现了IRecycle接口,就可以存入该队列中,而不需要关心具体的实现类型。这个接口定义了两个关键方法
OnFetch():在对象从池中取出时调用,用于执行初始化工作(例如重置状态、注册事件等)。OnRecycle():在对象回收前调用,用于清理或重置对象状态(例如注销事件、释放资源等)。Fetch 逻辑:方法约束:
where T : class, IRecycle, new()确保了被管理的对象必须实现IRecycle接口,并且可以通过无参构造函数创建。获取对象的方式:
- 通过
_GetPool(typeof(T))获取对应类型的对象池(如果不存在则创建新的队列)。 - 判断池中是否有可用对象:如果有则调用
Dequeue取出,否则通过new T()创建新对象。 - 调用对象的
OnFetch()方法完成初始化操作(例如注册事件、设置状态等)。 - 返回对象,并通过
as T进行类型转换。
- 通过
这种实现方式确保了在每次从池中取出对象前,都能通过 OnFetch 方法对对象进行了必要的初始化,保证对象处于可用状态。
该方法通过传入对象的类型来获取或创建对应的队列。
获取对象的方式:
- 判断是否存在该类型的对象池,如果不存在就创建该类型的对象池并将其添加到字典中。
- 如果存在就获取该类型的对象池。
回收对象的方法
该方法在对象使用完毕后,进行调用 Recycle 方法然后将对象放回池中。
- 判断对象是否为空
- 调用对象的
OnRecycle()方法:此方法通常用于清理、解除事件注册、释放使用过的资源等,这样可以确保对象在下次取用前处于一个全新的状态。 - 然后根据对象类型,调用
_GetPool(go.GetType())获取对应的队列,然后使用Enqueue将对象加入队列。
示例演示
关键步骤:
- 在类中去实现
IRecycle这个接口,实现这个接口就要去实现接口中所声明的所有方法。 - 在通过
Fetch方法创建对象时会调用该对象中的OnFetch()进行初始化。 - 回收方法实现:
- 在事件结束后调用
OnRelease进行回收,调用该方法会通过Recycle先调用OnRecycle()方法,进行比如:清理状态、注销事件和释放使用过的资源等。然后将对象重新放入对象池中,等待下次复用。
总结
通过这种方式去管理游戏中的对象,可以减少了对象频繁创建的性能开销,进而避免游戏卡顿。
热门推荐
清炒莴笋,鲜嫩爽口的秘密
连廊护栏材质对比,锌钢、铝合金及玻璃,谁的性价比更高?
感冒汤水食疗 | 12款食谱对抗咳嗽/发烧/喉咙痛症状
贪杯伤身,谨防上消化道出血
打车出行全攻略:从平台选择到安全乘车的实用指南
游戏渠道反作弊解决方案:精准打击假量、拉人和代充等作弊行为
水银体温针摔碎了该如何正确处理?别再用抹布擦了!这才是正确的做法
星空有约丨都说“四五清明”,今年为啥不一样?
重要信息发到了一个错误的邮箱里,如何挽救
智慧农业土壤墒情监测站:现代农业的新利器
孩子不善于交朋友?这样引导让孩子成为社交小达人!
警惕!水果这样洗越洗越脏!你中招没?
体温计怎么用?四种常见体温计使用方法详解
空调保养的重要性(空调清洁与维护)
跟腱炎可以按摩好吗?
量子百年系列之2:物质秩序的量子法则——泡利不相容原理
喝银耳汤会发胖吗?专业医生解读其热量与健康饮用指南
喝银耳汤会发胖吗?
警校体能测试标准高到离谱?真实数据揭秘:普通人能达标吗?
英国如何买地铁票
6200万年前的化石解开了与人类有关哺乳动物的百年之谜
网球肘的病因、症状、诊断、治疗及 4个缓解动作
什么是三方托管及其运作模式?三方托管存在哪些风险?
新生儿额头有红色印记怎么办
家用跑步机配速多少合适?家用跑步机配速指南
比亚迪的矛与欧盟的盾
提升英语之听力技巧:专业指南与实用策略
投影仪投屏-Win10笔记本无线连接投影仪的设置步骤
2025年广州社保缴费基数及比例最新标准
“铜博士”跌破数月上升趋势线,华尔街缘何继续看多?