先聊聊对象池吧 ,说白了就是我们把经常实例化的东西经常实例 然后又删除。这应该是常人的操作吧。而对象池的作用就是把后面哪一部分放到一个list里面,把它设置成setactive(false)。当我们再实例的时候然后从list中取。总体来说很简单。
首先我们假如要生成一个子弹,过会我们需要生产一个炮弹,对于这2中物体,我们应该生成2个池子 然后用一个总池子去管理这2个小池子了,这些应该很好理解吧,当然这个池子在任何时候都可以被调用,所以这个池子应该是个单例。我建议单例 最好去用单例组件那样去写。至于单例组件怎么写,我在下次 消息出来机制中给大家详细的讲。这里有不讲了。
首先我们先看一下一个小池子的书写吧,我们定义这个类为objectpool。这个池子应该有最基本的3个方法吧 首先初始化吧。这让我们知道这个池子里面是回收什么的,是可以生成什么的。接下来就是实例化一个游戏物体方法,回收一个游戏物体。同时也应该有一些辅助方法。例如将池子销毁掉方法,说实在的话 不知道怎么和你们讲具体的代码 ,我还是贴代码。然后再代码中去讲解吧。
using System;
using System.Collections.Generic;
using UnityEngine;
using Object = UnityEngine.Object;
public class ObjectPool
{
public event Action<GameObject> OnSpawnedEvent;
public event Action<GameObject> onDespawnedEvent;
public GameObject Prefab;//注释这个池子里面的原始东西。这个物体时子弹的话 ,那么这个池子就只生成和销毁子弹了。
public int InstancesToPreallocate = 5;//池子里面最多能有个数
public int InstancesToAllocateIfEmpty = 1;//池子最少的个数
public int HardLimit = 5;//最多限制个数
public int InstancesToMaintainInPool = 5;
public bool PersistBetweenScenes = false;
private Stack<GameObject> _gameObjectPool;
public void Initialize()//初始化池子
{
_gameObjectPool = new Stack<GameObject>(InstancesToPreallocate);
AllocateGameObjects(InstancesToPreallocate);
}
public void ClearStack()//这里池子用的数据结构是栈 你也可以用链表,队列都行。这个方法是清空栈
{
if (_gameObjectPool.Count > InstancesToMaintainInPool)
{
for (int i = InstancesToMaintainInPool; i < _gameObjectPool.Count; i++)
{
Object.Destroy(_gameObjectPool.Pop());
}
}
}
public GameObject Spawn()//实例化一个游戏物体
{
var go = Pop();
return go;
}
public void RecycleObj(GameObject ob)//回收一个游戏物体,将物体设置成不可见,然后放到栈中
{
ob.transform.parent = Pools.Instance.gameObject.transform;
ob.SetActive(false);
_gameObjectPool.Push(ob);
}
private GameObject Pop()
{
if (_gameObjectPool.Count > 0)
{
return _gameObjectPool.Pop();
}
AllocateGameObjects(InstancesToAllocateIfEmpty);
return Pop();
}
public void ClearPool(bool shouldDestroyAllManagedObjects)//qing
{
while (_gameObjectPool.Count > 0)
{
var go = _gameObjectPool.Pop();
if (shouldDestroyAllManagedObjects)
Object.Destroy(go);
}
}
private void AllocateGameObjects(int count)
{
for (int n = 0; n < count; n++)
{
GameObject go = Object.Instantiate(Prefab.gameObject) as GameObject;
go.name = Prefab.name;
if (go.transform as RectTransform)
{
go.transform.SetParent(Pools.Instance.Transform, false);
go.SetActive(false);
}
else
{
go.transform.parent = Pools.Instance.Transform;
go.SetActive(false);
}
_gameObjectPool.Push(go);
}
}
}
当我们在看别人的代码结构的时候 一些私有方法是可以不用看的,当你要具体了解某个类的作用的时候,这是才开始看。当然接口是最需要看。这只是一种类型物体的池子。我们下节看一个主管理池子的大池子。