对象池的概念
对象池是个什么东西呢?对象池是用来管理对象的一个池子,当一个物体需要大量的创建和删除时,由于函数Instantiate十分的耗费性能,所以要用对象池来管理,在加载界面中先在池子里面创建一些游戏物体,然后需要的时候从池子里取出,当使用完成后再放回池子里,利用SetActive来代替Instantiate和Destroy。对象池呦三种模式:队列模式,链表模式,栈模式,三种模式大同小异,看个人喜好使用
对象池里只有一个预制体
队列对象池
public GameObject pre;//预制体
private Queue<GameObject> quepool=new Queue<GameObject>();//空池子
public GameObject Creat()
{
GameObject go=null;
//如果池子里有对象就把它取出 如果没有再创建
if(quepool.Count>0)
{
go=quepool.Dequeue();
go.SetActive(true);
return go;
}
return Instantiate(pre);
}
public void Destory(GameObject go)
{
quepool.Enqueue(go);
go.SetActive(false);
}
``
对象池里面有多个预制体
思路:让对象池的使用者来提供自己的预制体,让其作为参数来传递给对象池。使用字典来管理(Dictionary)
字典:Dictionary<key , value > key是键 一个key代表一类物体 value是值 (感觉和数据结构中的Map一毛一样)
物体的Id:每一个正在使用的物体的id都是唯一的,物体销毁后id就会失效,由于使用对象池,物体不会被销毁,因此可以使用GetInstanceID来获取物体的ID并使用
创建和销毁的伪代码
创建物体时提供参数prefab,把prefab转为物体种类的ID,判断对象池中是否有这个ID,如果没有则需要将这个类型加入对象池中。将物体返回之前要记录,记录保存在outPool中
销毁物体时要判断是否存在于outPool字典中,如果不存在则它不是从对象池中取出的,如果存在则将他从outPool中删除,添加到pool中
代码
private Dictionary<int , Queue< GameObject >> pool=new Dictionary<int , Queue< GameObject >>();//对象池本身的物体
private Dictionary<GameObject ,int>outPool=new Dictionary<GameObject, int>();//记录离开的物体
//取物体
public GameObject Creat(GameObject prefab)
{
int id=prefab.GetInstanceID();
GameObject go=GetForId(id);
if(go==null)
{
go=Instantiate<GameObject>(prefab);
//不存在键就把他加进去
if(!pool.ContainKey(id))
{
pool.Add(go,new Queue<GameObject>());
}
}
outpool.Add(go,id);
return go;
}
public GameObject GetForId(int id)
{
//在池子里寻找物体,如果没有这个id或者id的池子里没有物体 就返回null
if(!pool.ContainKey(id)||pool[id].Count==0) return null;
GameObject go=pool[id].Dequeue();//如果里面有就把物体出队
go.SetActive(true);
return go;
}
//存物体
public void Destory(GameObject prefab)
{
if(!outpool.ContainKey(prefab)) return;//输出池子为空说明预制体不存在对象池里面
int id=outpool[prefab];
prefab.transform.parent=transform;
prefab.SetActive(false);
pool[id].Enqueue(prefab);
outpool.Remove(go);
}
测试功能
此处测试的为存单个物体的对象池,若测多个物体的则将Pool改为ObjPool即可
做个预制体吧
public Pool pool;//为啥预制体也要设成public?因为要在测试代码中调用它 预制体的public生成后都是空的
要用代码给他们重新赋值
public Pool pool;
void Update()
{
Vector3 dir = transform.position - Vector3.zero;
transform.position += dir.normalized * Time.deltaTime * 2;
if(Vector3.Distance(transform.position,Vector3.zero)>10)
{
pool.Destory(gameObject);
}
}
开始测试
public GameObject pre;
Pool pool;
void Start()
{
pool=GameObject.Find("Pool").GetComponent<Pool>();
}
void Update()
{
if(Input.GetKeyDown(KeyCode.Space))
{
for(int index=0;index<1000;index++)
{
GameObject go=pool.Creat();
go.GetComponent<Pre>().pool=pool;
go.transform.position=Random.onUnitSphere*2;//onUnitSphere:返回半径为1.0的球面上的随机点
go.transform.setparent=transform;
}
}
}