unity中对象池的简单使用

为什么使用对象池
当一个游戏需要频繁的创建和销毁对象时,为了不增加GC的性能消耗,可以考虑使用回收对象来打到复用的目的。(适用于飞机大战类,消除类,射击类,moba类等游戏)
什么是对象池
为了回收和复用对象,我们使用一个集合来存储不使用的对象,当需要使用该对象时,再从集合中取出,这样一个工具类称之为对象池。
对象池的实现
ObjectPool:对存储对象的集合进行了适当的封装,用于单个游戏对象(预制体)的回收和复用。
PoolManager:对ObjectPool单个游戏对象的进一步封装,可以用于创建多个对象(预制体)的回收和复用,可以更方便的使用对象池。(对象池模块化)
IPoolRelease:对象池回收对象时的还原接口,继承后对象自动还原初始值。

using UnityEngine;
using System.Collections.Generic;
/// <summary>
/// 对象池
/// </summary>
public class ObjectPool {

    private GameObject prefab;
    private Stack<GameObject> pool = new Stack<GameObject>();

    public ObjectPool(GameObject _prefab)
    {
        prefab = _prefab;
    }

    //取对象
    public GameObject Get()
    {
        if (pool.Count > 0)
        {
            GameObject go = pool.Pop();
            go.SetActive(true);
            return go;
        }
        else
        {
            GameObject go = GameObject.Instantiate(prefab);
            return go;
        }
    }

    //回收,存对象
    public void Save(GameObject go)
    {
        go.transform.SetParent(PoolManager.Instance.transform);
        go.SetActive(false);
        //调用回收对象的重置方法,(接口中定义)
        IPoolRelease ipool = go.GetComponent<IPoolRelease >();
        if(ipool!=null)
        {
            ipool.OnReset();
        }
        pool.Push(go);
    }
}

using UnityEngine;
using System.Collections.Generic;
/// <summary>
/// 1.有且只有一个唯一的实例
/// 2.只能自己赋值,别人不能修改(私有的构造)
/// </summary>
public class PoolManager : MonoBehaviour {

    //私有的静态实例
    private static PoolManager _instance = null;

    //懒汉式 单例模式
    //共有的唯一的,全局访问点
    public static PoolManager Instance
    {
        get
        {
            if (_instance == null)
            {
                _instance = GameObject.FindObjectOfType<PoolManager>();
                if (_instance == null)
                {
                    GameObject go = new GameObject("PoolManager");
                    _instance = go.AddComponent<PoolManager>();
                }
            }
            return _instance;
        }
    }
    public GameObject[] prePrefabs;
    //饿汉式 单例模式
    private void Awake()
    {
        if (_instance == null)
            _instance = this;
        else
            Destroy(gameObject);


        InitPool();
    }

    private Dictionary<string, ObjectPool> dic = new Dictionary<string, ObjectPool>();


    void InitPool()
    {
        //提前初始化的对象池
        foreach (var prefab in prePrefabs)
        {
            CreatPool(prefab.name, prefab);
        }
    }
    /// <summary>
    /// 创建对象池
    /// </summary>
    /// <param name="poolName">对象池名字</param>
    /// <param name="prefab">对象池对应的预制体</param>
    public void CreatPool(string poolName,GameObject prefab)
    {
        if (!dic.ContainsKey(poolName))
        {
            dic[poolName] = new ObjectPool(prefab);
        }
    }

    /// <summary>
    /// 获取对象池对象
    /// </summary>
    /// <param name="poolName">对象池名字</param>
    /// <returns></returns>
    public GameObject Get(string poolName)
    {
        ObjectPool pool;
        if(dic.TryGetValue(poolName,out pool))
        {
            return pool.Get();
        }
        else
        {
            Debug.LogError("对象池:" + poolName + " 不存在!!!");
            return null;
        }
    }

    /// <summary>
    /// 回收对象
    /// </summary>
    /// <param name="poolName">对象池的名字</param>
    /// <param name="go">对象</param>
    public void Save(string poolName,GameObject go)
    {
        ObjectPool pool;
        if (dic.TryGetValue(poolName, out pool))
        {
            pool.Save(go);
        }
        else
        {
            Debug.LogError("对象池:" + poolName + " 不存在!!!");
        }
    }
}

public interface IPoolRelease {
    void OnReset();
}
}

猜你喜欢

转载自blog.csdn.net/weixin_44431724/article/details/107671309