1.创建工程
工程结构
2.接口和对象池物体的基类实现
定义一个接口,用来实现对象池中物体的回收、生成。
定义一个方法,所有的对象池中所挂载脚本的基类。继承自MonoBehaviour和IReusable,并实现这个接口。
3.实现对象池中子池子的编写
首先创建一个脚本,取名为SubPool。
- 创建一个LIst集合,用来保存所有属于该池子的所有物体。
- 创建一个GameObject类型的Prefab
- 创建一个string类型的名字属性,总的池子会根据这个名字查找对应的子池子。
- 创建一个Transform类型的父物体的位置,用来设置新生成池子的位置。
创建构造方法,参数为一个Transform和GameObject类型,让字段中的预制和父物体分别等于这两个参数。
创建取出物体方法,创建一个空的临时变量,,遍历List集合,如果当前集合中的有物体的active为false,则把这个物体赋值给临时变量。遍历完毕以后,判断这个临时变量是否为空,如果为空,则创建一个出来,加入到List中。把创建出来的active设置为true,发送一条调用OnSpawn的方法,返回这个临时变量。
创建取出物体的方法,参数为一个要取出的GameObject类型。判断这个物体是否存在List集合中,如果存在,发送一条调用UnSpawn的方法,并把这个物体设置为false。
创建取出所有物体方法,遍历List集合,调用取出物体的方法。
最后,创建判断一个物体是否存在List集合的方法,使用Contains进行判断。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 对象池中的子池子
/// 每一个子池子是一个类型
/// </summary>
public class SubPool : MonoBehaviour
{
/// <summary>
/// 存储改子池子中的所有物体
/// </summary>
List<GameObject> m_objects = new List<GameObject>();
/// <summary>
/// 预制,池子中的类型
/// </summary>
GameObject m_Prefab;
/// <summary>
/// 父物体的信息
/// </summary>
Transform m_Parent;
/// <summary>
/// 总池子根据名字来查找子池子
/// </summary>
public string Name
{
get { return m_Prefab.name; }
}
/// <summary>
/// 构造方法
/// </summary>
/// <param name="parent"></param>
/// <param name="go"></param>
public SubPool(Transform parent, GameObject go)
{
m_Prefab = go;
m_Parent = parent;
}
/// <summary>
/// 取得物体的方法
/// </summary>
/// <returns></returns>
public GameObject OnSpawn()
{
GameObject go = null;
foreach (var item in m_objects)//判断集合中是否有物体为隐藏状态(隐藏——可用),如果有就赋值给go
{
if (!item.activeSelf)
{
go = item;
}
}
if (go == null)//经过遍历以后,说明集合为空或者集合中没有可用的物体,就创建出来,添加到集合中
{
go = GameObject.Instantiate<GameObject>(m_Prefab);
go.transform.parent = m_Parent;
m_objects.Add(go);
}
go.SetActive(true);
go.SendMessage("OnSpawn", SendMessageOptions.DontRequireReceiver);
return go;
}
/// <summary>
///回收单个物体
/// </summary>
/// <param name="go"></param>
public void UnSpawn(GameObject go)
{
if (Contain(go))
{
go.SendMessage("OnUnSpawn", SendMessageOptions.DontRequireReceiver);
go.SetActive(false);
}
}
/// <summary>
/// 回收所有的物体
/// </summary>
public void UnSpawnAll()
{
foreach (var item in m_objects)
{
UnSpawn(item);
}
}
/// <summary>
/// 物体是否存在池子中
/// </summary>
/// <param name="go"></param>
/// <returns></returns>
public bool Contain(GameObject go)
{
return m_objects.Contains(go);
}
}
资源池的实现
创建脚本取名为ObjectPool;
- 创建一个string类型的字段,当作资源目录,和名字组成,生成新的池子。
- 创建一个字典,key为string,Value为SubPool,string为名字。
创建取出物体的方法,参数为:name(名字),Transform(父物体的位置)。创建一个SubPool的临时变量,判断字典中是否存在参数中的名字,如果不存在,就调用创建新的池子的方法,如果取在,就根据参数名字找到字典中对应的Value赋值给临时变量,返回临时变量。
创建新池子的方法,参数为:name(名字),Transform(父物体的位置)。定义一个string类型的变量path,来当作Resources加载的的路径,path就等于开始时定义的一个string类型的字段加上"/"在加上name。使用Resource创建出这个物体,调用SubPool中的构造方法,把使用Resource创建后的物体传进去。加入到字典当中。回收单个物体和全部回收和子池子是一样的,这里就不写了直接把代码上来。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ObjectPool : MonoSingleton<ObjectPool>
{
/// <summary>
/// 资源目录
/// </summary>
public string ResourcesDir;
/// <summary>
/// 存储所有的子池子
/// string为名字
/// </summary>
Dictionary<string, SubPool> m_pools = new Dictionary<string, SubPool>();
/// <summary>
/// 取出物体
/// </summary>
/// <param name="name">子池子的名字</param>
/// <param name="parent">父物体的位置信息</param>
/// <returns></returns>
public GameObject Spawn(string name, Transform parent)
{
SubPool pool = null;
if (!m_pools.ContainsKey(name))//判断池子是否存在 不存在就创建,存在就调用该池子中取出物体的方法
{
//生成新的池子
RegieterNew(name,parent);
}
pool = m_pools[name];
return pool.OnSpawn();
}
/// <summary>
/// 回收单个物体
/// </summary>
/// <param name="go">要取出的物体</param>
public void Unspwan(GameObject go)
{
SubPool pool = null;
foreach (var item in m_pools.Values)//遍历所有的子池子,调用子池子中判断物体是否存在的方法
{
if (item.Contain(go))//存在:就调用这个池子中的回收方法
{
pool = item;
break;
}
}
pool.UnSpawn(go);
}
/// <summary>
/// 回收所有的物体
/// </summary>
public void UnspawnAll()
{
foreach (var item in m_pools.Values)//遍历所有的子池子,调用子池子中判断物体是否存在的方法
{
item.UnSpawnAll();//存在:就调用这个池子中的回收所有的方法
}
}
/// <summary>
/// 创建新的池子
/// </summary>
void RegieterNew(string name,Transform parent)
{
//资源目录
string path = ResourcesDir + "/" + name;
//生成物体
GameObject go = Resources.Load<GameObject>(path);
//生成池子
SubPool pool = new SubPool(parent,go);
m_pools.Add(pool.Name,pool);
}
}
下面是我的微信公众号,可以关注一下,问我拿一些学习视频。
本人正在学习中,如果有错误欢迎各位大佬提携提携小弟,感激不尽!!!