首先创建如下四个脚本
之后在场景中创建两个空节点:
一个挂载PoolManager作为对象池管理器。
一个挂载TestManager作为对象创建的位置。
之后在场景中创建一个Cube挂载TestObject作为对象池的子对象。
代码:
using UnityEngine;
/// <summary>
/// 创建出来的对象的父类
/// </summary>
public class PoolObject : MonoBehaviour
{
public virtual void OnObjectReuse() { }
protected void Destroy()
{
gameObject.SetActive(false);
}
}
using UnityEngine;
public class PoolManager : MonoBehaviour
{
Dictionary<int, Queue<ObjectInstance>> poolDictionary = new Dictionary<int, Queue<ObjectInstance>>();
#region 单例
private static PoolManager _instance;
public static PoolManager instance
{
get
{
if (_instance == null)
{
_instance = FindObjectOfType<PoolManager>();
}
return _instance;
}
}
private void Awake()
{
//防止有多个单例
if (_instance == null)
_instance = this;
else
Destroy(gameObject);
}
#endregion
public void CreatePool(GameObject prefab, int poolSize)//创建对象池的函数
{
/// <summary>
///同一个Prefab,不管是Inspector挂上去的还是用Resource.Load()动态加载的,这个ID都是一样的。
///只有当Instantiate成对象之后,每个对象间的ID才会有区别。
///不同的Prefab,ID是不一样的。
/// </summary>
int poolKey = prefab.GetInstanceID();//获取游戏对象的唯一ID标识
//创建预制体并修改基础信息
GameObject poolHolder = new GameObject(prefab.name + "_pool");
poolHolder.transform.parent = transform;
if (!poolDictionary.ContainsKey(poolKey))
{
poolDictionary.Add(poolKey, new Queue<ObjectInstance>());
for (int i = 0; i < poolSize; i++)
{
//gon = newGameObject
ObjectInstance gon = new ObjectInstance(Instantiate(prefab) as GameObject);
poolDictionary[poolKey].Enqueue(gon);
gon.SetParent(poolHolder.transform);
}
}
}
public void ReuseObject(GameObject prefab, Vector3 position, Quaternion rotation)//对象的重用函数
{
int poolKey = prefab.GetInstanceID();
if (poolDictionary.ContainsKey(poolKey))
{
//gor = reuseGameObject
ObjectInstance gor = poolDictionary[poolKey].Dequeue();//将队列头部弹出
poolDictionary[poolKey].Enqueue(gor);//将弹出的内容重新压进队列作为队尾
gor.Reuse(position,rotation);
}
}
public class ObjectInstance
{
GameObject gameObject;
Transform transform;
bool hasPoolObjectComponent;
PoolObject poolObjectScript;
//构造函数,创建对象池中的子对象进行初始化使用
public ObjectInstance(GameObject objectInstance)
{
gameObject = objectInstance;
transform = gameObject.transform;
gameObject.SetActive(false);
if (gameObject.GetComponent<PoolObject>())
{
hasPoolObjectComponent = true;
poolObjectScript = gameObject.GetComponent<PoolObject>();
}
else
{
Debug.LogError("无对象类");
}
}
public void Reuse(Vector3 position, Quaternion rotation)
{
if (hasPoolObjectComponent)
{
poolObjectScript.OnObjectReuse();
}
gameObject.SetActive(true);
transform.position = position;
transform.rotation = rotation;
}
public void SetParent(Transform parent)
{
transform.parent = parent;
}
}
}
using UnityEngine;
public class TestObject : PoolObject
{
TrailRenderer trail;
float trailTime;
private void Awake()
{
trail = GetComponent<TrailRenderer>();
trailTime = trail.time;
}
void Update()
{
transform.localScale += Vector3.one * Time.deltaTime;
transform.Translate(Vector3.forward * Time.deltaTime * 25);
}
public override void OnObjectReuse()
{
//base.OnObjectReuse();
trail.time = -1;
Invoke("ResetTrail",0.1f);
Invoke("Destroy", 5.0f);
transform.localScale = Vector3.one;
}
private void ResetTrail()
{
trail.time = trailTime;
}
}
using UnityEngine;
public class TestManager : MonoBehaviour
{
public GameObject prefab;
private void Start()
{
//创建对象池
PoolManager.instance.CreatePool(prefab, 30);
}
// Update is called once per frame
void Update()
{
//调用对象池中的对象
if (Input.GetKeyDown(KeyCode.Space))
{
PoolManager.instance.ReuseObject(prefab,Vector3.zero,Quaternion.identity);
}
}
}