使用对象池的目的是为了避免频繁实例化同一对象造成的内存浪费。
资源池类
- 资源池名称,预制,最大数量、获取pool中资源的方法
using System.Collections.Generic;
using UnityEngine;
using System;
/// <summary>
/// 资源池类
/// </summary>
[Serializable]
public class GameObjectPool
{
public string name;//资源池名称
[SerializeField]
private GameObject prefab;//预制资源
[SerializeField]
private int MaxAmount;//最大数量
[NonSerialized]
private List<GameObject> goList = new List<GameObject>();//当前资源池存储资源的集合
/// <summary>
/// 从资源池中获取实例
/// </summary>
public GameObject GetInst()
{
//从pool中查找是否有空闲实例
//如果经过foreach以后依然没有返回 说明pool中没有可以使用的实例
foreach (GameObject go in goList)
{
if (go.activeInHierarchy == false)
{
go.SetActive(true);
return go;
}
}
//此时应该创建实例 (注意pool容量是否满了)
if(goList.Count>=MaxAmount)//如果大于最大数量
{
//销毁第一个物体 并从pool中移除
GameObject.Destroy(goList[0]);
goList.RemoveAt(0);
}
GameObject temp= GameObject.Instantiate(prefab)as GameObject;//实例化
goList.Add(temp);//实例化对象添加到pool
return temp;//返回实例化对象
}
}
资源池类的集合
- 继承ScriptableObject 可以把类转换为自定义配置资源
- 对象池类的集合
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// GameObjectPoolList资源池集合
/// 继承ScriptableObject表示把自定义的类变为自定义资源配置的文件
/// </summary>
public class GameObjectPoolList : ScriptableObject
{
public List<GameObjectPool> poolList;
}
生成自定义资源配置文件
- 注意路径格式
using UnityEngine;
using UnityEditor;
public class PoolManagerEditor {
[MenuItem("工程框架/创建Pool定制资源配置文件")]
static void CreateGameObjectPoolList()
{
//创建一个自定义资源配置文件 GameObjectPoolList
GameObjectPoolList poolList = ScriptableObject.CreateInstance<GameObjectPoolList>();
//路径
string path = "Assets/Framework/Resources/gameobjectpool.asset";
AssetDatabase.CreateAsset(poolList,path);
AssetDatabase.SaveAssets();
}
}
然后我们就得到了可以自定义资源的配置文件。
如图所示,这种自定义资源配置文件不仅可以保持字符串数据,还可以拖动预制资源进行配置。
资源池管理类
- 类单例 用于全局调用
- 读取配置文件
- 获取方法不在此类中写,而是方法在对象池类,在当前类中调用。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PoolManager {
//对象池管理类单例
private static PoolManager _instance;
public static PoolManager Instance
{
get
{
if (_instance == null)
{
_instance = new PoolManager();
}
return _instance;
}
}
//路径
private static string poolConfigPathTrefix = "Assets/Framework/Resources/";
//文件名
private const string poolConfigPathMiddle = "gameobjectpool";
//文件后缀
private const string poolConfigPahtPostfix = ".asset";
//完整路径
public static string PoolConfigPath
{
get
{
return poolConfigPathTrefix + poolConfigPathMiddle + poolConfigPahtPostfix;
}
}
//定义用于存储获取到配置文件信息的字典
private Dictionary<string, GameObjectPool> poolDict;
//构造方法
private PoolManager()
{
//根据名字加载 自定义的配置文件
GameObjectPoolList PoolList = Resources.Load<GameObjectPoolList>(poolConfigPathMiddle);
poolDict = new Dictionary<string, GameObjectPool>();
foreach (GameObjectPool pool in PoolList.poolList)
{
poolDict.Add(pool.name, pool);//文字文件信息传入字典
}
}
//得到实例对象
public GameObject GetInst(string poolName)
{
GameObjectPool pool;
//通过名字获取指定对象池
if(poolDict.TryGetValue(poolName,out pool))
{
//返回资源池中的一个对象
return pool.GetInst();
}
Debug.LogWarning("通过名字没找到");
return null;
}
}
使用
//通过名字获取到一个实例对象
PoolManager.Instance.GetInst("Bullet");