本次介绍两个脚本GameObjectPool游戏对象池类和MonoSingLeton单例模式类。
在Unity中不论是在游戏中或者是别的应用场景,我们有时候会需要重复产生相同的物体并销毁掉,例如子弹就得不断生成不断销毁。但这样是很消耗性能的。所以有的大佬就设计了游戏对象池这个概念。
游戏对象池脚本挂在一个空物体上,玩家在Unity中不需要使用 Instantiate() 方法进行创建物体。而是用我GameObjectPool脚本中的CreateObject(string key,GameObject go,Vector3 pos,Quaternion rat)进行创建。依次是预制件名称、预制件对象、三维坐标数据、旋转数据。当使用这个方法创建时物体时,该物体会成为对象池的子物体,而当需要到销毁时对象池会将该物体隐藏,若再次需要用到,则重新设置物体的坐标和旋转并启用。若对象池内的物体不够用了才会重新生成一个对象。
游戏对象池在游戏中只能有一个,所以需要将他设计为单例模式。只需要让游戏对象池继承他便可。然后调用他的instance方法就可以了。
————————————————————————————————————————
MonoSingLeton脚本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
///
/// 单例模式挂载脚本
///
public abstract class MonoSingLeton
{
private static T m_Instance = null;
//3.
//设计阶段,写脚本没有挂在物体上,希望脚本单例模式
//运行时,需要这个脚本唯一实例,第1次,调用instance
public static T instance
{
get
{
if(m_Instance == null)
{
m_Instance = FindObjectOfType(typeof(T)) as T;
if (m_Instance == null)
{
m_Instance = new GameObject("Singleton of" + typeof(T).ToString(), typeof(T)).GetComponent
m_Instance.Init();
}
}
return m_Instance;
}
}
private void Awake()
{
if (m_Instance == null)
{
m_Instance = this as T;
}
}
//提供初始化一种选择
public virtual void Init() { }
//当程序退出时做清理工作,单例模式对象=null
private void OnApplicationQuit()
{
m_Instance = null;
}
}
——————————————————————————————————————
游戏对象池脚本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
///
/// 游戏对象池
///
public class GameObjectPool : MonoSingLeton
{
//1.创建池
private GameObjectPool()
{
}
//static private GameObjectPool obj = new GameObjectPool();
////提供得到对象的唯一通道
//static public GameObjectPool GetObject()
//{
// return obj;
//}
private Dictionary
//2.创建一个对象并使用对象
public GameObject CreateObject(string key,GameObject go,Vector3 pos,Quaternion rat)
{
//1.查找池中有无可用的游戏对象
GameObject tempGo = FindUsable(key);
//2.池中有从池中返回
if (tempGo != null)
{
tempGo.transform.position = pos;
tempGo.transform.rotation = rat;
tempGo.SetActive(true); //表示当前正在使用
}
else//3.池中没有加载,放入池中再返回
{
tempGo = Instantiate(go, pos, rat) as GameObject;
//放入池中
Add(key, tempGo);
}
tempGo.transform.parent = transform;
return tempGo;
}
private GameObject FindUsable(string key)
{
if (cache.ContainsKey(key))
{
//从列表中找出未激活的游戏物体
return cache[key].Find((p) => !p.activeSelf);
}
return null;
}
private void Add(string key,GameObject go)
{
//检查池中有没有需要的key,没有的话则创建对应列表
if (!cache.ContainsKey(key))
{
cache.Add(key,new List
}
cache[key].Add(go);
}
//3. 释放资源:从池中删除对象
//3.1 释放部分:按key释放
public void Clear(string key)
{
if (cache.ContainsKey(key))
{
//销毁场景中游戏物体
for (int i = 0; i < cache[key].Count; i++)
{
Destroy(cache[key][i]);
}
//紧紧移除了字典中对象地址
cache.Remove(key);
}
}
//3.2 释放全部
public void ClearAll()
{
List
for (int i = 0; i < list.Count; i++)
{
Clear(list[i]);
}
}
//4. 回收对象【从画面中消失】
//4.1 即使回收对象
public void CollectObject(GameObject go)
{
go.SetActive(false);
}
//4.2 延时回收对象 协程
public void CollectObject(GameObject go,float delay)
{
StartCoroutine(CollectDelay(go,delay));
}
private IEnumerator CollectDelay(GameObject go,float delay)
{
yield return new WaitForSeconds(delay);
CollectObject(go);
}
}