永久单例对象池(多对象)

//对象池全局存在继承永久单例类(上一篇文章中的单例)
添加功能:
与之前的对象池不同的是,新对象池可以存放不同种类的对象,并且可以通过枚举存放的路径进行加载并且实例化,调用时返回一个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);
    }
}

(实验成功了!我现在没有录屏软件 等有时间了再发!)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值