对象池一、对象池的简单定义
对象池是Unity经常使用的内存管理服务。 对于需要频繁生成和消失的对象,可以减少创建每个对象的系统开销。 当对象需要消失时,我们不(false),然后将其放入池中(Queue)。 当我们需要再次显示一个新的对象时,我们首先去池中查看是否有隐藏的对象,然后将其取出(true),如果池中没有可用的,则再次显示。
2、使用对象池的原因
在Unity游戏开发过程中,经常会创建一些新的对象。 如果数量少,也是可以接受的。 如果新创建的对象数量较多,对内存来说将会是一个很大的隐患。 例如,在射击游戏中,每发射一颗子弹,都必须创建一个新的子弹对象,而且子弹数量巨大。 可想而知,一个游戏中会创建多少个这样的新物体,那么如果创建这些子弹的话。 游戏发挥关键且持续的作用是可以理解的。 问题是,子弹发射后,几秒钟后就不再有任何意义了。 一般会自动隐藏,也就是我们所说的(假),所以游戏场景中会出现很多不活动的物体。
由于对象池中的对象只是(假)并没有真正销毁,所以一般用于游戏中经常使用或者需要大量生成的对象。 并不是所有的物体都能使用这项技术,否则得不偿失。
3.创建并使用简单的对象池
首先我们生成一个对象池类,里面的内容很简单。 首先池中有一个Queue,用来存储对象,然后实现两个方法,一个用于取出对象,一个用于放入对象。 取对象时,如果池中有可用对象,则取出一个,如果没有,则取出一个; 当对象被放入时,该对象(false)将被放入池中。下图是一个简单的效果
首先有一个.cs,用于将其他脚本写入单例模式
namespace Utilty
{
public class Singleton
{
private static T instance;
public static T GetInstance()
{
if (instance == null)
{
instance = (T)Activator.CreateInstance(typeof(T), true);
}
return instance;
}
}
}
复制代码
.cs 用于加载和生成游戏对象
using System.Collections.Generic;
using UnityEngine;
//通用框架
namespace Utilty
{
public class AssetsManager : Singleton
{
protected AssetsManager()
{
assetsCache = new Dictionary();
}
//缓存字典
private Dictionary assetsCache;
//获取资源
public virtual T GetAssets(string path) where T : Object
{
//先查看缓存池中有没有这个资源
if (assetsCache.ContainsKey(path))
{
//直接将这个资源返回
return assetsCache[path] as T;
}
else
{
//通过Resource.Load去加载资源
T assets = Resources.Load(path);
//将新资源加载到缓存池里
assetsCache.Add(path,assets);
//返回资源
return assets;
}
}
//卸载未使用的资源
public void UnloadUnusedAssets()
{
//卸载
Resources.UnloadUnusedAssets();
}
}
//加载图片
public class SpriteManager : Singleton
{
}
public class PrefabManager : Singleton
{
private PrefabManager() { }
public GameObject CreateGameObjectByPrefab(string path)
{
//获取预设体
GameObject prefab = AssetsManager.GetInstance().GetAssets(path);
//生成
GameObject obj = Object.Instantiate(prefab);
// 返回
return obj;
}
public GameObject CreateGameObjectByPrefab(string path, Vector3 pos, Quaternion qua)
{
//生成对象
GameObject obj = CreateGameObjectByPrefab(path);
//设置坐标和旋转
obj.transform.position = pos;
obj.transform.rotation = qua;
//返回
return obj;
}
public GameObject CreateGameObjectByPrefab(string path, Transform parent, Vector3 localPos, Quaternion localQua)
{
//生成对象
GameObject obj = CreateGameObjectByPrefab(path);
//设置父物体
obj.transform.SetParent(parent);
//设置坐标和旋转
obj.transform.localPosition = localPos;
obj.transform.localRotation = localQua;
//返回
return obj;
}
}
}
复制代码
.cs用于通过对象池生成并回收游戏对象
using System.Collections.Generic;
using UnityEngine;
namespace Utilty
{
public class ObjectPool : Singleton
{
//私有构造
private ObjectPool()
{
pool = new Dictionary>();
}
//对象池
private Dictionary> pool;
//通过对象池生成游戏对象
public GameObject SpawnObject(string name)
{
GameObject needObj;
//查看是否有该名字所对应的子池,且子池中有对象
if (pool.ContainsKey(name) && pool[name].Count > 0)
{
//将0号对象返回
needObj = pool[name][0];
//将0号对象从List中移除
pool[name].RemoveAt(0);
}
else
{
//直接通过Instantiate生成
needObj = PrefabManager.GetInstance().CreateGameObjectByPrefab(name);
//修改名称(去掉Clone)
needObj.name = name;
}
//设置为激活
needObj.SetActive(true);
//返回
return needObj;
}
///
/// 回收游戏对象到对象池
///
///
public void RecycleObj(GameObject Objname)
{
//防止被看到,设置为非激活哦
Objname.SetActive(false);
if (pool.ContainsKey(Objname.name))
{
//将当前对象放入对象子池
pool[Objname.name].Add(Objname);
}
else
{
//创建该子池并将对象放入
pool.Add(Objname.name, new List { Objname });
}
}
}
}
复制代码
.cs 用于延迟收集对象
using System.Collections;
using UnityEngine;
using Utilty;
public class PoolObject : MonoBehaviour
{
private void onEnable()
{
StartCoroutine(DelayRececle(2));
}
//延迟回收协程
IEnumerator DelayRececle(float interval)
{
//等待几秒
yield return new WaitForSeconds(interval);
//回收当前对象
ObjectPool.GetInstance().RecycleObj(gameObject);
}
}
复制代码
Demo.cs用于对象池技术的简单使用
using UnityEngine;
using Utilty;
public class Demo : MonoBehaviour
{
private void Update()
{
if (Input.GetKeyDown(KeyCode.J))
{
GameObject go = ObjectPool.GetInstance().SpawnObject("Prefab");
go.transform.position = Vector3.zero;
go.transform.rotation = Quaternion.identity;
go.GetComponent().velocity = Vector3.zero;
}
}
}