对象池,为了减小内存压力而产生的一种资源回收方式。
方式一:
下方脚本演示了一个简单的对象池的实现逻辑:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
///< summary >
/// 对象池
/// </summary>
public class GameObjectPool : MonoBehaviour
{
//内部容器,用于存入缓存的对象
private Dictionary<string, List<GameObject>> cache = new Dictionary<string, List<GameObject>>();
/// <summary>
/// 生产物体
/// </summary>
public GameObject CreateObject(string key, GameObject go, Vector3 position, Quaternion quaternion)
{
//有:key对应列表中有没有可用(非活动状态)的物体
var tempGo = FindUsable(key);
if (tempGo != null)
{
//有:设置后返回可用物体
tempGo.transform.position = position;
tempGo.transform.rotation = quaternion;
tempGo.SetActive(true);
}
else
{
//没有:(场景中没有,内存中也没有)创建物体后添加cache,
tempGo = Instantiate(go, position, quaternion) as GameObject;
Add(key, tempGo);
}
return tempGo;
}
/// <summary>
/// 将对象放入缓存
/// </summary>
private void Add(string key, GameObject newObject)
{
//创建key,创建key的列表
if (!cache.ContainsKey(key))
cache.Add(key, new List<GameObject>());
cache[key].Add(newObject);
}
/// <summary>
/// 找对应key的列表中没有没可用的物体
/// </summary>
private GameObject FindUsable(string key)
{
//有Key: 找非活动状态的物体
if (cache.ContainsKey(key))
{
return cache[key].Find(p => !p.activeSelf);
}
return null;
}
/// <summary>
/// 即时回收
/// </summary>
/// <param name="go">要回收的对象</param>
public void CollectObject(GameObject go)
{
go.SetActive(false);
}
/// <summary>
/// 延时回收
/// </summary>
/// <param name="go">要回收的对象</param>
/// <param name="delay">延时时长</param>
public void CollectObject(GameObject go, float delay)
{
//开启协程
StartCoroutine(Delay(go, delay));
}
/// <summary>
/// 用于回收的协程方法
/// </summary>
public IEnumerator Delay(GameObject go, float delay)
{
//等待delay之后,
yield return new WaitForSeconds(delay);
//调用即时回收
CollectObject(go);
}
/// <summary>
/// 将key对象的缓存物体从池中清除(销毁)
/// </summary>
/// <param name="key"></param>
public void Clear(string key)
{
if (cache.ContainsKey(key))
{
while (cache[key].Count > 0)
{
//销毁每个物体
Destroy(cache[key][0]);
//删除列表中的空引用
cache[key].RemoveAt(0);
}
//删除key
cache.Remove(key);
}
}
/// <summary>
/// 清空池中物体
/// </summary>
public void ClearAll()
{
//遍历所有的key
List<string> keys = new List<string>(cache.Keys);
//逐个清除
while (cache.Count > 0)
{
Clear(keys[0]);
keys.RemoveAt(0);
}
}
}
测试效果
上边的例子中,所有生成的物体不会被主动销毁而是被隐藏起来,需要使用时直接显示出来,重复利用。可以满足一些常规的需求了。
方式二(用PoolManager插件)
另外你也可以使用PoolManager插件来达到这种效果
这里可以下载http://www.qudong51.net/qudong/851.html
新建节点挂这个脚本,下方可以提前添加想要实例的预制体,并提供了一些数量限制、自动销毁清理之类的选项
调用
///从内存池里面取一个GameObjcet
Transform momo = spawnPool.Spawn("momo");
//清空池子
using UnityEngine;
using System.Collections;
using PathologicalGames;
public class NewBehaviourScript : MonoBehaviour {
SpawnPool spawnPool;
PrefabPool refabPool;
void Start()
{
spawnPool = PoolManager.Pools["Shapes"];
refabPool = new PrefabPool(Resources.Load<Transform>("momo"));
}
void OnGUI()
{
if(GUILayout.Button("初始化内存池"))
{
if(!spawnPool._perPrefabPoolOptions.Contains(refabPool))
{
refabPool = new PrefabPool(Resources.Load<Transform>("momo"));
//默认初始化两个Prefab
refabPool.preloadAmount = 2;
//开启限制
refabPool.limitInstances = true;
//关闭无限取Prefab
refabPool.limitFIFO = false;
//限制池子里最大的Prefab数量
refabPool.limitAmount =5;
//开启自动清理池子
refabPool.cullDespawned = true;
//最终保留
refabPool.cullAbove = 10;
//多久清理一次
refabPool.cullDelay = 5;
//每次清理几个
refabPool.cullMaxPerPass =5;
//初始化内存池
spawnPool._perPrefabPoolOptions.Add(refabPool);
spawnPool.CreatePrefabPool(spawnPool._perPrefabPoolOptions[spawnPool.Count]);
}
}
if(GUILayout.Button("从内存池里面取对象"))
{
///从内存池里面取一个GameObjcet
Transform momo = spawnPool.Spawn("momo");
}
if(GUILayout.Button("清空内存池"))
{
//清空池子
spawnPool.DespawnAll();
}
}
}
这个来自雨松:https://www.xuanyusong.com/archives/2974
using UnityEngine;
using System.Collections;
using PathologicalGames;
public class AssembleModel : MonoBehaviour
{
//创建
public Transform Spawner(string prefabs, string names = "", string SpawnPools = "prefabs")
{
Transform inst;
SpawnPool shapesPool = PoolManager.Pools[SpawnPools];
inst = shapesPool.Spawn(Resources.Load<Transform>(prefabs));
if (names == "")
names = prefabs + Time.timeScale;
inst.name = names;
return inst;
}
//全体删除
public void Despawner(string SpawnPools = "prefabs")
{
SpawnPool shapesPool = PoolManager.Pools[SpawnPools];
shapesPool.DespawnAll();
}
//单个删除
public void Despawn(Transform transform, string SpawnPools = "prefabs")
{
SpawnPool shapesPool = PoolManager.Pools[SpawnPools];
shapesPool.Despawn(transform);
}
}
↑这个来自博客园用户“太粗难进”:https://www.cnblogs.com/big-zhou/p/4135380.html