[Unity工具]简易对象池

1、对象池

关于对象池的介绍有很多,这里就不详细说了。总的来说,例如弹幕游戏,会生成很多子弹,当子弹失效后,这些子弹会摧毁,这里就产生了问题。实例化子弹,摧毁子弹,涉及到内存分配和GC,会对性能又很大损耗。我们想重复利用这些已经生成了的子弹,不销毁他们,保存他们的引用,需要的时候调用他们,减少了GC,提高性能。

2、Unity中的对象池

将脚本挂在空物体上,面板上会出现PoolSetting,数量代表需要回收的物体种类,prefab代表物体,name代表索引的名字,PreCount代表预分配的数量。
简单做了一个Unity工程的例子github地址:https://github.com/MangoWAY/UnityObjectPool

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GameObjectPool : MonoBehaviour {
    [System.Serializable]
    public struct PoolGameObject
    {
        public GameObject Prefab;//需要生成的物体
        public string Name;//物体的名字
        public int PreCount;//预分配的数量
    }
    public PoolGameObject[] PoolSetting;
    private Dictionary<string, List<GameObject>> mPool;//一个key值对应一个list,一个list存一类对象
    private Dictionary<string, Transform> mDirectory;//一个key对应一个目录,便于管理

    private void Start()
    {
        InitPool();
    }

    //初始化对象池
    private void InitPool()
    {
        mPool = new Dictionary<string, List<GameObject>>();
        mDirectory = new Dictionary<string, Transform>();
        string keyTemp = ""; 
        for (int i = 0; i < PoolSetting.Length; i++)
        {
            //生成物体对应的目录层级
            keyTemp = PoolSetting[i].Name + "(Clone)";
            GameObject directory = new GameObject();
            directory.transform.SetParent(transform);
            directory.name = keyTemp;
            mDirectory.Add(keyTemp, directory.transform);

            //根据设定的大小,生成物体
            mPool.Add(keyTemp, new List<GameObject>());
            for (int j = 0; j < PoolSetting[i].PreCount; j++)
            {
                var go = Instantiate(PoolSetting[i].Prefab, directory.transform);
                go.name = keyTemp;
                go.SetActive(false);
                mPool[keyTemp].Add(go);
            }
        }
    }

    //从对象池里根据名字取物体
    public GameObject GetGameObject(string name)
    {
        GameObject go = null;
        string keyTemp = name + "(Clone)";
        if (!mPool.ContainsKey(keyTemp))
        {
            Debug.LogError("Get: The pool didn't contanin the key");
            go = null;
        }

        else if (mPool[keyTemp].Count != 0)
        {
            go = mPool[keyTemp][0];
            go.SetActive(true);
            mPool[keyTemp].RemoveAt(0);
        }
        else
        {
            for (int i = 0; i < PoolSetting.Length; i++)
            {
                if (PoolSetting[i].Name+"(Clone)" == keyTemp)
                {
                    go = Instantiate(PoolSetting[i].Prefab, transform);
                    break;
                }
            }
        }
        return go;
    }

    //使用完成后的游戏对象返回对象池
    public void ReturnGameObject(GameObject go)
    {
        if (!mPool.ContainsKey(go.name))
        {
            Debug.LogError("Return: The pool didn't contanin the key");
            return;
        }
        go.transform.SetParent(mDirectory[go.name]);
        mPool[go.name].Add(go);
        go.SetActive(false);
    }
}

3、测试

这里写图片描述
这里写图片描述

猜你喜欢

转载自blog.csdn.net/wayway0554/article/details/81333464