Unity制作最简单好用的对象池
之前找过各种对象池demo,综合找到个最简单好用的对象池写法,只需要一个脚本,参考原文
原文链接
对这个脚本小做点改动,可以自行扩展几个重载方法。上代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PoolManager
{
/// <summary>
/// 对象池
/// </summary>
private Dictionary<string, List<GameObject>> pool;
/// <summary>
/// 预设体
/// </summary>
private Dictionary<string, GameObject> prefabs;
#region 单例
private static PoolManager instance;
private PoolManager()
{
pool = new Dictionary<string, List<GameObject>>();
prefabs = new Dictionary<string, GameObject>();
}
public static PoolManager Instance
{
get
{
if (instance == null)
{
instance = new PoolManager();
}
return instance;
}
}
#endregion
/// <summary>
/// 从对象池中获取对象
/// </summary>
/// <param name="objName">Prefab的名字</param>
/// <param name="position">生成时的位置</param>
/// <param name="quaternion">生成时的四元数</param>
/// <returns></returns>
public GameObject GetObj(string objName, Vector3 position, Quaternion quaternion)
{
//结果对象
GameObject result = null;
//判断是否有该名字的对象池
if (pool.ContainsKey(objName))
{
//对象池里有对象
if (pool[objName].Count > 0)
{
//获取结果
result = pool[objName][0];
//激活对象
result.transform.position = position;
result.transform.rotation = quaternion;
result.SetActive(true);
//从池中移除该对象
pool[objName].Remove(result);
//返回结果
return result;
}
}
//如果没有该名字的对象池或者该名字对象池没有对象
GameObject prefab = null;
//如果已经加载过该预设体
if (prefabs.ContainsKey(objName))
{
prefab = prefabs[objName];
}
else //如果没有加载过该预设体
{
//加载预设体
prefab = Resources.Load<GameObject>("Prefabs/" + objName);
//更新字典
prefabs.Add(objName, prefab);
}
//生成
result = Object.Instantiate(prefab);
result.transform.position = position;
result.transform.rotation = quaternion;
//改名(去除 Clone)
result.name = objName;
//返回
return result;
}
/// <summary>
/// 从对象池中获取对象
/// </summary>
/// <param name="objName">Prefab的名字</param>
/// <param name="parent">生成时的父级</param>
/// <returns></returns>
public GameObject GetObj(string objName, Transform parent)
{
//结果对象
GameObject result = null;
//判断是否有该名字的对象池
if (pool.ContainsKey(objName))
{
//对象池里有对象
if (pool[objName].Count > 0)
{
//获取结果
result = pool[objName][0];
//设置父级
result.transform.SetParent(parent);
//激活对象
result.SetActive(true);
//从池中移除该对象
pool[objName].Remove(result);
//返回结果
return result;
}
}
//如果没有该名字的对象池或者该名字对象池没有对象
GameObject prefab = null;
//如果已经加载过该预设体
if (prefabs.ContainsKey(objName))
{
prefab = prefabs[objName];
}
else //如果没有加载过该预设体
{
//加载预设体
prefab = Resources.Load<GameObject>("Prefabs/" + objName);
//更新字典
prefabs.Add(objName, prefab);
}
//生成
result = Object.Instantiate(prefab);
//设置父级
result.transform.SetParent(parent);
//改名(去除 Clone)
result.name = objName;
result.SetActive(true);
//返回
return result;
}
/// <summary>
/// 回收对象到对象池
/// </summary>
/// <param name="objName"></param>
public void RecycleObj(GameObject obj)
{
//设置为非激活
obj.SetActive(false);
//判断是否有该对象的对象池
if (pool.ContainsKey(obj.name))
{
//放置到该对象池
pool[obj.name].Add(obj);
}
else
{
//创建该类型的池子,并将对象放入
pool.Add(obj.name, new List<GameObject>() { obj });
}
}
}
调用时直接单例调用,例如
生成这个预设物
PoolManager.Instance.GetObj("People",transform);
回收
PoolManager.Instance.RecycleObj(gameObject);
注释写的也很清楚。记录下来,以后有用直接看。