当前位置: 代码迷 >> 综合 >> U3D框架(三):对象池
  详细解决方案

U3D框架(三):对象池

热度:73   发布时间:2024-02-08 18:48:48.0

对象池原理:将子弹之类的物体回收关闭,再次调用的时候打开,这样可以防止数据被频繁的创建和删除。

如果只是单个对象池,我们用一个list即可实现。

不过为了方便,项目中通常会把这部分单独提炼出来。

总游戏池的代码类似如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class ObjectPool
{public static readonly ObjectPool Inst = Singleton<ObjectPool>.Inst;/// <summary>/// 对象池,字典中与key值对应的是数组(arraylist)(例:key为手枪子弹  对应arraylist[手枪子弹,手枪子弹,手枪子弹。。。。。。 ])。/// </summary>private Dictionary<string, List<GameObject>> Pool;/// <summary>/// 从对象池中获取对象/// </summary>/// <param name="_objName"></param>/// <returns></returns>public GameObject GetObj(string _objAffiliation, string _objName){GameObject _result = null;//判断是否有该名字的对象池      //对象池中有对象if (Pool.ContainsKey(_objName) && Pool[_objName].Count > 0){//Debug.Log("调用对象池:" + _objName);//获取这个对象池中的第一个对象_result = Pool[_objName][0];if(_result==null) Debug.LogError(Pool[_objName].Count+ _objName);//激活对象_result.SetActive(true);//从对象池中移除对象Pool[_objName].Remove(_result);//返回结果return _result;}//如果没有该名字的对象池或者该名字对象池没有对象//Debug.Log(_objAffiliation + "  " + _objName);GameObject _prefab = /*Main.UploadResource.transform.Find("" + _objAffiliation + "/" + _objName).gameObject;*/null;//实例化物体_result = UnityEngine.Object.Instantiate(_prefab);//改名 去除Clone_result.name = _objName;_result.SetActive(true);return _result;}/// <summary>/// 回收对象到对象池/// </summary>public void RecycleObj(GameObject _obj, bool _isMap = false){if (_obj == null || !_obj.activeInHierarchy) return;_obj.SetActive(false);//如果有该对象的对象池,直接放在池子中if (Pool.ContainsKey(_obj.name)){Pool[_obj.name].Add(_obj);}else//如果没有该对象的对象池,创建一个该类型的池子,并将对象放入{//Debug.Log("新建一个对象池:" + Obj.name);Pool.Add(_obj.name, new List<GameObject>() { _obj });}}/// <summary>/// 移除所有的数组/// </summary>public void RemoveAll(){Pool.Clear();}
}

 

单例对象池类似如下:

/// <summary>
/// 简易的池
/// </summary>
public class SimplePool
{private List<GameObject> objPool;//存储物体的池private string poolName;private string path;//创建池public void CreatPool(string _name,string _path){objPool = new List<GameObject>();poolName = _name;path = _path;}//创建物体public GameObject CreatObj(){GameObject obj = null;if (objPool.Count > 0){obj = objPool[0];objPool.Remove(obj);}else{//Debug.Log(path + "/" + poolName);obj = UnityEngine.Object.Instantiate( Resources.Load(path+ "/" + poolName) as GameObject);//Debug.Log(obj);}obj.name = poolName;obj.transform.position = -100 * Vector3.one;obj.SetActive(true);        //Debug.LogError("剩余长度"+objPool.Count);return obj;    }//回收物体public void RecycleObj(GameObject obj){if (obj==null || obj.activeSelf == false) return;obj.SetActive(false);objPool.Add(obj);//Debug.LogError("新增长度" + objPool.Count);}//清除池public void ClearPool(){for (var idx = objPool.Count - 1; idx >= 0; idx--){GameObject _obj = objPool[idx];objPool.Remove(_obj);GameObject.Destroy(_obj);}objPool.Clear();}
}

需要注意的是,在Resources首次加载物体的时候,会有短暂的卡顿,所以最好对于占用内存比较大的物体,使用异步加载。

  相关解决方案