不管何种语言,对象的创建与销毁都需要消耗一定的时间,Unity3D 也是如此,所以在场景中,如果某些对象需要频繁的创建与销毁,这个时候我们经常采用对象池技术,这样不仅可以降低对象的创建与销毁的带来的时间损耗,也是为了降低内存的占用。 我们在做项目的时候,如果同一个物体要用到好多次,我们就不要再用实例化了,因为每次创建一个新物体是很消耗资源的,引用对象池技术,顾名思义,把所有要用到的对象在初始化的时候都扔到这个池子里,想用的时候拿出来用,不想用的时候放回去,这样会大大节省资源!
【一共是一个Demo,两个版本,一个是一个对象的储存与获取,另一个版本是多个游戏对象的储存与获取,都写在一个类中的,下面就为大家分享一下对象池的实现】
DemoName:ObjectPool
Demo下载地址:http://pan.baidu.com/s/1kVdGLHd
using System.Collections;
using UnityEngine;
using System.Collections.Generic;
/// <summary>
/// 对象池管理脚本,无需挂载
/// </summary>
public class ObjectPools
{
#region 对象池
/// <summary>
/// 对象池1,创建单个对象
/// </summary>
List<GameObject> pools1;
/// <summary>
/// 以字典的方式储存对象到池中,int类型key,集合类型的value
/// </summary>
Dictionary<int, List<GameObject>> pools2;
//单例
private static ObjectPools singleton;
/// <summary>
/// 获取对象,单例
/// </summary>
/// <returns></returns>
public static ObjectPools GetInstance()
{
if (singleton == null)
{
singleton = new ObjectPools();
}
return singleton;
}
//构造函数初始化对象池
public ObjectPools()
{
pools1 = new List<GameObject>();
pools2 = new Dictionary<int, List<GameObject>>();
}
#endregion
#region 储存单个游戏对象到池中
/// <summary>
/// 储存单个游戏对象到池中
/// </summary>
/// <param name="gameObject">创建的游戏对象</param>
/// <param name="pos">位置</param>
/// <param name="rotation">旋转</param>
/// <returns>返回的对象</returns>
public GameObject SwpanObject(GameObject gameObject, Vector3 pos, Quaternion rotation)
{
//如果池中的对象数量大于0
if (pools1.Count > 0)
{
GameObject result = pools1[0]; //提取第一个对象
pools1.Remove(result); //从集合中清除提取的对象
result.SetActive(true); //设置当前对象激活
result.transform.position = pos; //设置对象的初始位置
result.transform.rotation = rotation; //设置对线下的初始旋转
return result; //返回游戏对象
}
//否则,直接实例化游戏对象并返回
return GameObject.Instantiate(gameObject, pos, rotation) as GameObject;
}
/// <summary>
/// 隐藏当前游戏对象并添加到池中
/// </summary>
/// <param name="gameObejct">游戏对象</param>
public void DestoryObject(GameObject gameObejct)
{
//关闭当前游戏对象显示
gameObejct.SetActive(false);
//添加到集合中
pools1.Add(gameObejct);
}
#endregion
#region 储存多个游戏对象到池中
/// <summary>
/// 实例化并储存游戏对象到池中
/// </summary>
/// <param name="gameObject">被创建的游戏对象</param>
/// <param name="pos">位置</param>
/// <param name="rotation">旋转</param>
/// <returns>返回当前游戏对象</returns>
public GameObject SwpanObject2(GameObject gameObject, Vector3 pos, Quaternion rotation)
{
//获取到当前对象的ID(每个游戏对象都有各自的ID)
int key = gameObject.GetInstanceID();
//如果池中包含key当前游戏对象的key值(游戏对象的ID)
if (pools2.ContainsKey(key))
{
//如果池中的对象数量大于0
if (pools2[key].Count > 0)
{
//提取第一个对象(key就是ID(ID就是相对应的游戏对象),0代表的是这个key中第一个对象)
GameObject result = pools2[key][0];
result.SetActive(true); //激活显示当前对象
pools2[key].Remove(result); //从池中清除对象游戏对象
result.transform.position = pos; //设置初始位置
result.transform.rotation = rotation; //设置初始旋转
return result; //返回提取的游戏对象
}
}
//否则,实例化对象并接收
GameObject res = GameObject.Instantiate(gameObject, pos, rotation) as GameObject;
//储存游戏对象的ID,转换成字符串
res.name = gameObject.GetInstanceID().ToString();
//返回场景的游戏对象
return res;
}
/// <summary>
/// 隐藏当前游戏对象并添加到池中
/// </summary>
/// <param name="gameObject">游戏对象</param>
public void DestoryObject2(GameObject gameObject)
{
//当前游戏对象不激活
gameObject.SetActive(false);
//获取当前游戏对象的key值,转换成int类型
int key = int.Parse(gameObject.name);
//如果池中不包含key值对应的游戏对象
if (!pools2.ContainsKey(key))
{
//添加对象到池中,并开辟value空间
pools2.Add(key, new List<GameObject>());
}
//否则直接添加key对应的游戏对象到池中
pools2[key].Add(gameObject);
}
#endregion
#region 协程,延迟关闭游戏对象的显示
/// <summary>
/// 协程,延迟隐藏游戏对象,单个游戏对象
/// </summary>
/// <param name="gameObject">隐藏的游戏对象</param>
/// <param name="time">隐藏的时间间隔</param>
/// <returns></returns>
public IEnumerator IEDestory(GameObject gameObject, float time)
{
yield return new WaitForSeconds(time);
GetInstance().DestoryObject(gameObject);
}
/// <summary>
/// 协程,延迟隐藏游戏对象,游戏对象数组
/// </summary>
/// <param name="gameObject">隐藏的游戏对象</param>
/// <param name="time">隐藏的时间间隔</param>
/// <returns></returns>
public IEnumerator IEDestory2(GameObject gameObject, float time)
{
yield return new WaitForSeconds(time);
GetInstance().DestoryObject2(gameObject);
}
#endregion
}
using UnityEngine;
/// <summary>
/// 对象池的调用,挂载到空物体即可
/// </summary>
public class GameManager : MonoBehaviour
{
//储存单个游戏对象到对象池中
public GameObject player;
//需要利用到对象池的游戏对象数组(同时创建多个游戏对象)
public GameObject[] players;
void Update()
{
//单个游戏对象的插件
if (Input.GetMouseButtonDown(2))
{
//按下鼠标中键的时候创建一个游戏对象
GameObject go =
ObjectPools.GetInstance().SwpanObject(player, Vector3.zero, Quaternion.identity) as GameObject;
//开启协程,延迟隐藏对象
StartCoroutine(ObjectPools.GetInstance().IEDestory(go, 2f));
}
//游戏对象数组的创建
if (Input.GetMouseButtonDown(0))
{
//按下左键,创建数组中第1个游戏对象
GameObject go = ObjectPools.GetInstance().SwpanObject2(players[0],
Vector3.zero, Quaternion.identity);
//开启协程,延迟隐藏对象
StartCoroutine(ObjectPools.GetInstance().IEDestory2(go, 2f));
}
if (Input.GetMouseButtonDown(1))
{
//按下右键,创建数组中第2个游戏对象
GameObject go = ObjectPools.GetInstance().SwpanObject2(players[1],
Vector3.zero, Quaternion.identity);
//开启协程,延迟隐藏对象
StartCoroutine(ObjectPools.GetInstance().IEDestory2(go, 2f));
}
}
}