当前位置: 移动技术网 > IT编程>开发语言>JavaScript > U3D框架(三):对象池

U3D框架(三):对象池

2020年08月10日  | 移动技术网IT编程  | 我要评论

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

如果只是单个对象池,我们用一个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首次加载物体的时候,会有短暂的卡顿,所以最好对于占用内存比较大的物体,使用异步加载。

本文地址:https://blog.csdn.net/Tel17610887670/article/details/107892624

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网