//对象池全局存在继承永久单例类(上一篇文章中的单例)
添加功能:
与之前的对象池不同的是,新对象池可以存放不同种类的对象,并且可以通过枚举存放的路径进行加载并且实例化,调用时返回一个GameObject对象
首先
//字典类型的容器用于存放对象池列表的索引
public Dictionary<string,List<GameObject>> _PoolDic = new Dictionary<string,List<GameObject>>();
与上一个对象池的思路一样,添加创建对象和销毁对象的方法:
创建对象的方法被我分离开成(从池中取出对象,和加载对象两种方法)
创建对象:
private GameObject CreateGameObject(string type ,string path)
{
if(_PoolDic.ContainsKey(type) && _PoolDic[type].Count > 0 )
{
GameObject obj = _PoolDic[type][0];
_PoolDic[type].RemoveAt(0);
obj.SetActive(true);
return obj;
}
//如果对象池为空 则加载一个新的对象
return LoadPrefeb(path);
}
private GameObject LoadPrefeb(string path)
{
GameObject obj = Resources.Load(path) as GameObject;
if(obj == null)
{
Debug.LogError("the path of Obj is null");
return null;
}
GameObject InsObj = GameObject.Instantiate(obj);
return InsObj;
}
这里函数私有是因为每次加载需要以路径作为参数非常不合适,所以在下面写了新的方法
接着是销毁对象(对象池回收对象)
//对象池回收不用的对象
public void DestoryGameObject(string type, GameObject DesGameObj)
{
if(DesGameObj == null)
{
return;
}
if(!_PoolDic.ContainsKey(type))
{
_PoolDic.Add(type,new List<GameObject>());
}
if(_PoolDic[type].Contains(DesGameObj))//防止重复删除同一个物体
{
return;
}
if(ObjParent == null)
{
ObjParent = new GameObject("PoolNode");
GameObject.DontDestroyOnLoad(ObjParent);
}
DesGameObj.transform.SetParent(ObjParent.transform);
DesGameObj.SetActive(false);
_PoolDic[type].Add(DesGameObj);
}
如上我们已经有了取出和回收对象的方法,接着我们就用一个枚举来存放我们需要的不同对象,并通过枚举的描述获得路径
枚举:
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using UnityEngine;
public class ObjPoolType
{
public enum Bullet
{
[Description("Bullet/Bullet1")]
Bullet1,
[Description("Bullet/Bullet2")]
Bullet2,
}
}
对象池中调用:
//通过类型创建对象
public GameObject CreateObjByBulletType(ObjPoolType.Bullet BulletType)
{
string strInfo = BulletType.ToString();
//得到枚举类型的描述
string path = GetEnumDescription(BulletType.GetType().GetField(strInfo));
return this.CreateGameObject(strInfo, path);
}
//通过枚举的类型得到枚举的描述
private string GetEnumDescription(FieldInfo objFieldInfo)
{
if (null == objFieldInfo)
{
return string.Empty;
}
object[] objs = objFieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);
if (objs == null || objs.Length == 0)
{
return string.Empty;
}
DescriptionAttribute da = objs[0] as DescriptionAttribute;
if (null == da)
{
return string.Empty;
}
return da.Description;
}
完整代码如下
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Reflection;
using UnityEngine;
//对象池全局只存在一个,使用单例模式
public class NewPool : TMonoSingleton<NewPool>,IInitializabe
{
GameObject ObjParent = null;
//字典类型的容器用于存放对象池列表的索引
public Dictionary<string,List<GameObject>> _PoolDic = new Dictionary<string,List<GameObject>>();
/*
从对象池中取出一个对象
*/
private GameObject CreateGameObject(string type ,string path)
{
if(_PoolDic.ContainsKey(type) && _PoolDic[type].Count > 0 )
{
GameObject obj = _PoolDic[type][0];
_PoolDic[type].RemoveAt(0);
obj.SetActive(true);
return obj;
}
//如果对象池为空 则加载一个新的对象
return LoadPrefeb(path);
}
private GameObject LoadPrefeb(string path)
{
GameObject obj = Resources.Load(path) as GameObject;
if(obj == null)
{
Debug.LogError("the path of Obj is null");
return null;
}
GameObject InsObj = GameObject.Instantiate(obj);
return InsObj;
}
//对象池回收不用的对象
public void DestoryGameObject(string type, GameObject DesGameObj)
{
if(DesGameObj == null)
{
return;
}
if(!_PoolDic.ContainsKey(type))
{
_PoolDic.Add(type,new List<GameObject>());
}
if(_PoolDic[type].Contains(DesGameObj))//防止重复删除同一个物体
{
return;
}
if(ObjParent == null)
{
ObjParent = new GameObject("PoolNode");
GameObject.DontDestroyOnLoad(ObjParent);
}
DesGameObj.transform.SetParent(ObjParent.transform);
DesGameObj.SetActive(false);
_PoolDic[type].Add(DesGameObj);
}
//通过类型创建对象
public GameObject CreateObjByBulletType(ObjPoolType.Bullet BulletType)
{
string strInfo = BulletType.ToString();
//得到枚举类型的描述
string path = GetEnumDescription(BulletType.GetType().GetField(strInfo));
return this.CreateGameObject(strInfo, path);
}
//通过枚举的类型得到枚举的描述
private string GetEnumDescription(FieldInfo objFieldInfo)
{
if (null == objFieldInfo)
{
return string.Empty;
}
object[] objs = objFieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);
if (objs == null || objs.Length == 0)
{
return string.Empty;
}
DescriptionAttribute da = objs[0] as DescriptionAttribute;
if (null == da)
{
return string.Empty;
}
return da.Description;
}
}
接下来我们写一段代码测试我们的对象池是否有作用
:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class NewPoolTest : MonoBehaviour
{
// Use this for initialization
void Start()
{
}
// Update is called once per frame
void Update()
{
if (Input.GetMouseButtonDown(0))
{
GameObject go = NewPool.Instance.CreateObjByBulletType(ObjPoolType.Bullet.Bullet1);
go.transform.position = new Vector3(0,0,0);
go.GetComponent<Rigidbody>().AddForce(Vector3.down * 1000);
}
if (Input.GetMouseButtonDown(1))
{
GameObject go = NewPool.Instance.CreateObjByBulletType(ObjPoolType.Bullet.Bullet2);
go.transform.position = new Vector3(0, 0, 0);
go.GetComponent<Rigidbody>().AddForce(Vector3.down * 1000);
}
}
}
子弹上添加:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class NewBullet : MonoBehaviour {
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
private void OnCollisionEnter(Collision collision)
{
NewPool.Instance.DestoryGameObject("Bullet1",gameObject);
}
}
(实验成功了!我现在没有录屏软件 等有时间了再发!)