13. 对象池
13-1. 对象池
- 作用:减少对象创建和销毁的次数,让对象可以重复使用
- 对象特点:使用频率高、使用次数多
- 对象类型:AssetBundle需要Unload、GameObject(UI、Entity、Sound)需要Destroy
传统对象池:
- 原理:先创建一定数量的对象、使用时从池子取,用完了还回去
- 特点:相同对象、多次使用
我们的对象池:
- 特点:对象可以是多种类型、短时间内可重复使用、过期自动销毁
- 设计原理:池内不创建对象,对象在外部创建,使用完放入对象池,再次使用从对象池取
创建Framework/ObjectPool/PoolObject
using UnityEngine;
//专门用来存放ObjectPool里放置的不同对象的数据类
public class PoolObject
{
//具体对象
public Object Object;
//对象名字
public string Name;
//最后一次使用时间,,,针对不同类型的对象有不同的有效时长,超过有效时长就销毁
public System.DateTime LastUseTime;
//生成实例,放入池子时,会记录一下上一次的使用时间
public PoolObject(string name, Object obj)
{
Name = name;
Object = obj;
LastUseTime = System.DateTime.Now;
}
}
对于AssetBundle和GameObject的存和取都不相同。AssetBundle不需要设置非激活。
创建Framework/ObjectPool/PoolBase
using System.Collections.Generic;
using UnityEngine;
public class PoolBase : MonoBehaviour
{
//自动释放时间/s
protected float m_ReleaseTime;
//上次释放资源的时间/毫微妙 1(秒) = 10000000(毫微秒)
protected long m_LastReleaseTime = 0;
//真正的对象池
protected List<PoolObject> m_Objects;
public void Start()
{
m_LastReleaseTime = System.DateTime.Now.Ticks;
}
//初始化对象池
public void Init(float time)
{
m_ReleaseTime = time;
m_Objects = new List<PoolObject>();
}
//取出对象
public virtual Object Spawn(string name)
{
foreach (PoolObject po in m_Objects)
{
if (po.Name == name)
{
//放在池子里的一定是还没有用到的,用到的就拿出来
m_Objects.Remove(po);
return po.Object;
}
}
return null;
}
//回收对象
public virtual void UnSpawn(string name, Object obj)
{
PoolObject po = new PoolObject(name, obj);
m_Objects.Add(po);
}
//释放,父类什么都不做
public virtual void Release()
{
}
private void Update()
{
//父类需要按给定时间执行一次Release,但是到底释放没有,需要根据继承父类的子类来确定,其内部的时间是否到了销毁时间
if (System.DateTime.Now.Ticks - m_LastReleaseTime >= m_ReleaseTime * 10000000)
{
//刷新时间
m_LastReleaseTime = System.DateTime.Now.Ticks;
Release();
}
}
}
public class GameObjectPool : PoolBase
{
//去物体:在池子中查找,如果有物体就激活,没有返回null
public override Object Spawn(string name)
{
Object obj = base.Spawn(name);
if (obj == null)
return null;
GameObject go = obj as GameObject;
go.SetActive(true);
return obj;
}
//存物体:把物体设置非激活,然后放进池子回收
public override void UnSpawn(string name, Object obj)
{
GameObject go = obj as GameObject;
go.SetActive(false);
go.transform.SetParent(this.transform, false);
base.UnSpawn(name, obj);
}
public override void Release()
{
base.Release();
foreach (PoolObject item in m_Objects)
{
if (System.DateTime.Now.Ticks - item.LastUseTime.Ticks >= m_ReleaseTime * 10000000)
{
Debug.Log("GameObjectPool release time:" + System.DateTime.Now);
Destroy(item.Object);
m_Objects.Remove(item);
//因为删除了list一项之后,不能用迭代器了,需要递归一下跳出
Release();
return;
}
}
}
}
public class AssetPool : PoolBase
{
public override UnityEngine.Object Spawn(string name)
{
return base.Spawn(name);
}
public override void UnSpawn(string name, UnityEngine.Object obj)
{