Unity 对象池
程序员文章站
2022-07-13 15:17:59
...
一、为什么使用对象池
1、如果不使用对象池会怎么样?假设FPS游戏按下鼠标左键发射子弹,然后子弹到达相应的位置删除对象。如果突然场景中出现了1000个人每人发射30颗子弹,可能会造成卡死等,具体什么现象没验证过。最主要的是会触发.Net的GC(垃圾回收机制),当触发了垃圾回收程序会卡。
2、对象池的优点:不用一直创建对象,把经常重发创建删除的对象全部储存在对象池中,如果使用直接从对象池中拿出,用完放回去,减少CPU负担。
3、对象池的缺点:减少CPU负担增加内存容量。增加的容量可以忽略不记。
二、对象池设计思路
三、对象池代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GameObjectPool : MonoSingleton<GameObjectPool> {
//对象池
private Dictionary<string, List<GameObject>> pool;
//初始化
public override void Initialize()
{
base.Initialize();
pool = new Dictionary<string, List<GameObject>>();
}
//代码思路是:创建对象时判断池中是否有对象如果没有那么创建,如果有判断是否可见如果不可见那么创建添加进池中
/// <summary>
/// 通过对象池创建对象
/// </summary>
/// <param name="key">key</param>
/// <param name="prefabGameObjec">预制件</param>
/// <param name="pos">位置</param>
/// <param name="rot">旋转</param>
/// <returns></returns>
public GameObject CreateGameObject(string key, GameObject prefabGameObjec, Vector3 pos, Quaternion rot)
{
GameObject tempGo = null;
//判断对象池中是否存在和能否使用
if (pool.ContainsKey(key))
tempGo = pool[key].Find(go => !go.activeInHierarchy);
//对象池没有key或者对象池中的对象不可用
if (tempGo == null)
{
//创建游戏对象
tempGo = GameObject.Instantiate(prefabGameObjec, pos, rot);
//如果key不存在创建列表
if (!pool.ContainsKey(key)) pool.Add(key, new List<GameObject>());
//添加进入对象池列表
pool[key].Add(tempGo);
}
//设置位置
tempGo.SetActive(true);
tempGo.transform.position = pos;
tempGo.transform.rotation = rot;
return tempGo;
}
/// <summary>
/// 回收对象
/// </summary>
/// <param name="go">游戏物体</param>
/// <param name="delayed">延迟时间</param>
public void RecycleGameObject(GameObject go,float delayed=0)
{
StartCoroutine(IeGameObjectDelayedHid(go,delayed));
}
private IEnumerator IeGameObjectDelayedHid(GameObject go, float delayed)
{
yield return new WaitForSeconds(delayed);
go.SetActive(false);
}
}