【简单实用框架】【对象池】【可移植】

GameObject对象池

  • IManager
  • IModel
  • GameObjectPool
  • ObjectPoolManager

方法

ObjectPoolManager

CreateGameObjectPool

创建对象池

DestroyGameObjectPool

删除对象池

GetGameObject

获得某个对象池里的对象

RecycleGameObject

回收对象

GameObjectPool

ClearAll

清除所有信息

GetGameObject

获得对象

RecycleGameObject

回收对象

ClearRedundantObjects

清除多余对象

CreateGameObjecet

创建对象

使用方法

//创建对象池(默认大小5)
ObjectPoolManager.Instance.CreateGameObjectPool("Basketball", "Basketball",20);
//获得某个对象池中对象
GameObject obj = ObjectPoolManager.Instance.GetGameObject("Basketball");
//回收对象
ObjectPoolManager.Instance.RecycleGameObject("Basketball",gameObject);
//删除对象池
ObjectPoolManager.Instance.DestroyGameObjectPool("Basketball");

全部代码

GameObjectPool

using MGPMFramework;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;

public class GameObjectPool : IModel
{
    private int m_Number;

    private int m_PoolSize;
    private string m_ResName;

    private GameObject m_OriginalRes;
    private GameObject m_GameObjectPoolParent;

    private Queue<GameObject> m_NotUseGameObjectPool;

    private bool m_SuccessFlag;
    public bool SuccessFlag { get { return m_SuccessFlag; } }
    public GameObjectPool(string name, string resName, GameObject objectPool, int poolSize)
    {
        m_Number = 0;

        m_SuccessFlag = true;
        m_NotUseGameObjectPool = new Queue<GameObject>(poolSize);

        m_PoolSize = poolSize;
        m_ResName = resName;

        string poolName = name + "Pool";
        m_GameObjectPoolParent = new GameObject(poolName);
        m_GameObjectPoolParent.transform.parent = objectPool.transform;

        OnInit();
    }

    /// <summary>
    /// 清除所有信息
    /// </summary>
    public void ClearAll()
    {
        while (m_NotUseGameObjectPool.Count > 0) Object.Destroy(m_NotUseGameObjectPool.Dequeue());

        m_NotUseGameObjectPool = null;

        m_PoolSize = 0;
        m_ResName = string.Empty;

        m_OriginalRes = null;

        Object.Destroy(m_GameObjectPoolParent);

        ResourcesManager.Instance.UnloadUnusedAssets();
    }

    /// <summary>
    /// 获得对象
    /// </summary>
    /// <returns></returns>
    public GameObject GetGameObject()
    {
        lock (m_NotUseGameObjectPool)
        {
            if (m_NotUseGameObjectPool.Count > 0)
            {
                return m_NotUseGameObjectPool.Dequeue();
            }
            else
            {
                GameObject obj = CreateGameObjecet();
                if (obj != null) return obj;
                else return null;
            }
        }
    }

    /// <summary>
    /// 回收对象
    /// </summary>
    /// <param name="obj"></param>
    public void RecycleGameObject(GameObject obj)
    {
        lock (m_NotUseGameObjectPool)
        {
            if (!m_NotUseGameObjectPool.Contains(obj))
            {
                obj.SetActive(false);
                obj.transform.parent = m_GameObjectPoolParent.transform;
                obj.transform.localPosition = Vector3.zero;
                m_NotUseGameObjectPool.Enqueue(obj);
            }
            else
            {
                Debug.LogError($"该对象已经归还过了,对象名{obj.name}");
            }

            ClearRedundantObjects();
        }
    }

    /// <summary>
    /// 清除多余对象
    /// </summary>
    private void ClearRedundantObjects()
    {
        while (m_NotUseGameObjectPool.Count > m_PoolSize) Object.Destroy(m_NotUseGameObjectPool.Dequeue());
    }

    /// <summary>
    /// 创建新对象
    /// </summary>
    /// <returns></returns>
    private GameObject CreateGameObjecet()
    {
        GameObject obj = GameObject.Instantiate(m_OriginalRes, m_GameObjectPoolParent.transform);
        if (obj != null)
        {
            obj.name = m_ResName +"_"+ m_Number;
            m_Number++;
            if (m_Number >= 1000) m_Number = 0;
            obj.SetActive(false);
            obj.transform.localPosition = Vector3.zero;
            return obj;
        }
        else
        {
            Debug.LogError($"实例化对象为空,资源名为{m_ResName}");
            return null;
        }
    }


    public void OnInit()
    {
        m_OriginalRes = ResourcesManager.Instance.Load<GameObject>(m_ResName);
        if (m_OriginalRes != null)
        {
            for (int i = 0; i < m_PoolSize; i++)
            {
                GameObject obj = CreateGameObjecet();
                if (obj != null) m_NotUseGameObjectPool.Enqueue(obj);
                else
                {
                    m_SuccessFlag = false;
                    break;
                }
            }
        }
        else
        {
            Debug.LogError($"资源{m_ResName}未找到");
            ClearAll();
            m_SuccessFlag = false;
        }
    }
}

ObjectPoolManager

using System.Collections.Generic;
using UnityEngine;
using MGPCommons.Class;

public class ObjectPoolManager : SingletonSuperMono<ObjectPoolManager>, IManager
{
    private GameObject m_ObjectPool;

    private Dictionary<string, GameObjectPool> m_AllObjectPoll;

    //初始化池
    //

    private void Awake()
    {
        OnInit();
    }

    public void OnInit()
    {
        m_ObjectPool = new GameObject("ObjectPool");
        DontDestroyOnLoad(m_ObjectPool);

        m_AllObjectPoll = new Dictionary<string, GameObjectPool>();
    }

    /// <summary>
    /// 创建对象池
    /// </summary>
    /// <param name="poolName">对象池名字</param>
    /// <param name="resName">资源名</param>
    /// <param name="poolSize">对象池大小</param>
    public void CreateGameObjectPool(string poolName, string resName,int poolSize = 5)
    {
        if (!m_AllObjectPoll.ContainsKey(poolName.Trim()))
        {
            GameObjectPool pool = new GameObjectPool(poolName, resName, m_ObjectPool, poolSize);
            if (pool.SuccessFlag) m_AllObjectPoll.Add(poolName, pool);
            else pool = null;
        }
        else
        {
            Debug.LogError($"对象池{poolName}Pool已经存在");
        }
    }

    /// <summary>
    /// 删除对象池
    /// </summary>
    /// <param name="name"></param>
    public void DestroyGameObjectPool(string poolName)
    {
        if (m_AllObjectPoll.ContainsKey(poolName.Trim()))
        {
            m_AllObjectPoll[poolName].ClearAll();
            m_AllObjectPoll.Remove(poolName);
        }
        else
        {
            Debug.LogError($"对象池{poolName}Pool不存在");
        }
    }

    /// <summary>
    /// 获取对象
    /// </summary>
    /// <param name="poolName"></param>
    /// <returns></returns>
    public GameObject GetGameObject(string poolName)
    {
        if (m_AllObjectPoll.ContainsKey(poolName.Trim()))
        {
            return m_AllObjectPoll[poolName].GetGameObject();
        }
        else
        {
            Debug.LogError($"对象池{poolName}Pool不存在");
            return null;
        }
    }

    /// <summary>
    /// 回收对象
    /// </summary>
    /// <param name="poolName"></param>
    /// <param name="obj"></param>
    public void RecycleGameObject(string poolName,GameObject obj)
    {
        if (m_AllObjectPoll.ContainsKey(poolName.Trim()))
        {
             m_AllObjectPoll[poolName].RecycleGameObject(obj);
        }
        else
        {
            Debug.LogError($"对象池{poolName}Pool不存在");
        }
    }
}

IManager

public interface IManager
{
    public void OnInit();
}

IModel

public interface IModel 
{
    public void OnInit();
}

移植使用注意

  1. ObjectPoolManager继承的单例类替换
  2. GameObjectPool.OnInitResourcesManager.Instance.Load<GameObject>(ResName)替换
  3. GameObjectPool.ClearAllResourcesManager.Instance.UnloadUnusedAssets()卸载资源替换
  4. 单例类和ResourcesManager在其它同专栏内。

问题记录

问题描述

工程启动以后,创建的所有子对象,竟然全部被删除了
在这里插入图片描述

触发环境

  1. 生成的对象有一个自定义脚本,该脚本的OnEnable中调用了三秒后回收本对象(类似子弹)
  2. 场景中有一个拖拽的子弹(非脚本生成,而是制作子弹时候的本体,本应删除,但是因遗漏可能没删除)

产生原因

  1. 有以上环境以后,项目启动,场景中的原物体也会触发OnEnable,进行回收。在这里插入图片描述
  2. 根据逻辑,队列中会出现11个(假设默认数量是10),然后就会删除第一个,在每个对象被生成的时候,也会调用一次OnEnable,所以第一个虽然被删除了,但是依旧会被回收,然后第二个就会被删除,依次类推。

结论

  1. 审查认为是使用Bug,所以做个记录,不进行修改,不要在OnEnable中调用回收函数
  2. 也不要在Start中调用,因为Start全局中调用一次。
  3. 场景中不要有遗留原物体

更新记录

  1. 2023/3/23 第一次更新
  2. 2023/4/18 更新了创建的子对象名称区别

我的Git

码云记录

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我是小狼君

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值