[Unity工具]简易对象池
程序员文章站
2022-03-21 09:01:05
...
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、测试
上一篇: iOS 即时通讯