版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/leonardo_Davinci/article/details/78646562
使用对象池的目的:增加频繁使用的游戏物体的 复用性 (游戏物体(敌人小兵)反复的创建与销毁 会消耗比较多的性能)
创建对象池的步骤:
1.创建一个存放对象的字典(对象池)
2.对对象池的操作方法
2.1创建对象 CreateObject()
2.2为对象池添加元素 Add()
2.3寻找可以使用的对象 FindUseObj()
2.4回收对象 CollectObject()
3.释放资源 Clear();
实现如下
1.实现一个单例,用于管理代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MonoSingleton<T>:MonoBehaviour where T:Component
{
private static T t;
public static T Intance{
get{
t = GameObject.FindObjectOfType(typeof(T)) as T;
if(t==null)
{
GameObject go = new GameObject();
t = go.AddComponent<T>();
go.name = t + "Object";
}
//在场景切换时不要销毁
DontDestroyOnLoad(t);
return t;
}
}
}
2.实现对象池
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 对象(频发使用的游戏物体) 子弹 技能 敌人
/// </summary>
public class ObjectPool : MonoSingleton<ObjectPool> {
//1.字段 池 例如:横扫千军 技能预制件(因为一个技能可能有多个预制件) 技能的复用性
private Dictionary<string, List<GameObject>> cache =
new Dictionary<string, List<GameObject>>();
int i = 0;
//2.方法
//2.1 创建
//工具类 加载资源 字典 名称 资源
/// <summary>
/// 创建显示对象
/// </summary>
/// <returns>The object.</returns>
/// <param name="key">对象名称</param>
/// <param name="go">对象的预制件</param>
/// <param name="position">对象的新位置</param>
/// <param name="quaternion">对象的角度</param>
public GameObject CreateObject(string key,GameObject go,Vector3 position,Quaternion quaternion)
{
//从池中取出可以使用的对象
GameObject tempgo = FindUseObj(key);
if(tempgo!=null)
{
tempgo.transform.position = position;
tempgo.transform.rotation = quaternion;
}
else{
tempgo = Instantiate(go, position, quaternion) as GameObject;
print(i++);
Add(key,tempgo);
}
tempgo.SetActive(true);
return tempgo;
}
/// <summary>
/// 为对象池添加元素
/// </summary>
/// <returns>The add.</returns>
/// <param name="key">Key.</param>
/// <param name="tempGo">Temp go.</param>
public void Add(string key, GameObject tempGo)
{
//对象池当中如果没有键(添加键)
if(!cache.ContainsKey(key))
{
cache.Add(key,new List<GameObject>());
}
//找到相应的值,为这个列表中添加tempGo
//List中的Add方法
//对象池中有键就直接在其list中添加值
cache[key].Add(tempGo);
}
/// <summary>
/// 寻找可以使用的对象
/// </summary>
/// <returns>The use object.</returns>
/// <param name="key">键</param>
public GameObject FindUseObj(string key)
{
//在池中且未被使用的对象
if(cache.ContainsKey(key))
{
//返回找到的第一个可用的对象(没有返回 null)
return cache[key].Find(p=>!p.activeSelf);
/*上面(泛型委托Lambda)这句话的意思
*p=cache[key][i]
*if(!cache[key][i].activeSelf=!p.activeSelf)
*
*实现的方法如下
* for(int i;i<cache[key].Count;i++)
* {
* if(!cache[key][i].activeSelf)
* return cache[key][i];
* }
*/
}
return null;
}
/// <summary>
/// 直接回收
/// </summary>
/// <param name="go">Go.</param>
public void CollectObject(GameObject go)
{
go.SetActive(false);
}
/// <summary>
/// 延迟回收
/// </summary>
/// <param name="go">Go.</param>
/// <param name="delay">Delay.</param>
public void CollectObject(GameObject go, float delay)
{
StartCoroutine(Collect(go,delay));
}
private IEnumerator Collect(GameObject go, float delay)
{
yield return new WaitForSeconds(delay);
CollectObject(go);
}
/// <summary>
/// 释放资源
/// </summary>
/// <returns>The clear.</returns>
/// <param name="key">Key.</param>
public void Clear(string key)
{
if(cache.ContainsKey(key))
{
//Destroy当中所有的对象
for (int i = 0; i < cache[key].Count;i++)
{
Destroy(cache[key][i]);
}
//清除键当中的所有值
//cache[key].Clear();
//清除这个键(键值一起清除)
cache.Remove(key);
}
}
/// <summary>
/// 释放所有对象池
/// </summary>
public void ClearAll()
{
var list = new List<string>(cache.Keys);
for (int i = 0; i < list.Count;i++)
{
Clear(list[i]);
}
}
}
3.简单使用对象池
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PoolTest : MonoBehaviour {
GameObject go;
GameObject item;
// Use this for initialization
void Start () {
//在Resources文件下加载Cube预制键
go = Resources.Load("Cube") as GameObject;
}
// Update is called once per frame
void Update () {
//按下空格创建一个Cube
if(Input.GetKeyDown(KeyCode.Space))
{
item = ObjectPool.Intance.CreateObject("Object1", go, Vector3.zero, new Quaternion(0, 0, 0, 0));
}
//按下左键执行回收
if(Input.GetMouseButtonDown(0))
{
if (item != null)
{
ObjectPool.Intance.CollectObject(item, 2);
}
}
//按下右键执行清除
if(Input.GetMouseButtonDown(1))
{
ObjectPool.Intance.Clear("Object1");
}
}
}