作为unity学习的小萌新,我最近学习了一下游戏对象池的写法(大佬可以跳过)
正式开始
什么是游戏对象池,通俗的讲就是一个装着一堆游戏物体的容器,他是用来管理各个游戏对象的,主要是可以节省游戏对象的频繁创造和销毁所带来的性能消耗。
简单的作用就是用来提高性能的
这里我们用一个设计模式和这个游戏对象池配合使用,这就是单例模式,为什么使用他呢,因为一个游戏只能有一个游戏对象池(当然比较大型的游戏,可以有多个),所以我们用单例模式来配合使用
由于构造函数是私有的,所以我们使用一下C#的反射来进行调用来实现
对象池有那些功能我们一个一个来讲述
1 池 (这里我们用Dictionary数据结构来存储)
2 创建游戏对象 (如果池里有,从池里拿,没有,则创建在池,然后再拿)
3 释放资源 (一类物体的释放)
4 回收对象(即时回收和延时回, 这里的延时可以使用Unity协程来实现)
我们一一实现
先来看单例抽象基类
using System;
using System.Reflection;
public abstract class SingletonBase<T>
where T : SingletonBase<T>
{
private static T instance = default;
public static T Instance
{
get
{
if (instance == null)
{
//获得类型参数
Type type = typeof(T);
var constructorInfoArray = type.GetConstructors(BindingFlags.NonPublic
| BindingFlags.Instance);
ConstructorInfo noParameterConstructorInfo = null;
foreach (var constructorInfo in constructorInfoArray)
{
ParameterInfo[] parameterInfoArray = constructorInfo.GetParameters();
if (parameterInfoArray.Length == 0)
{
noParameterConstructorInfo = constructorInfo;
break;
}
}
if (noParameterConstructorInfo == null)
{
throw new NotSupportedException("No constructor without 0 parameter");
}
instance = (T)noParameterConstructorInfo.Invoke(null);
}
return instance;
}
}
}
我们有了这个抽象基类,我们实现单例模式就非常方便了,只需要继承并写一个私有构造函数就可以了(这里使用反射技术来使用他的私有函数)
主代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 游戏对象池
/// </summary>
public class GameObjectPool : SingletonBase<GameObjectPool>
{
//创建池
Dictionary<string, List<GameObject>> pool =
new Dictionary<string, List<GameObject>>();
private GameObjectPool() { }
//创建使用池的元素【游戏对象】 一个游戏对象并使用对象
//池中有从池中返回;池中没有,加载放入池中再返回
public GameObject CreateObject(string key, GameObject go,
Vector3 position, Quaternion quaternion)
{
//1.查找池中有无可用游戏对象
GameObject temogo = FindUseable(key);
//2.池中有从池中返回
if (temogo != null)
{
temogo.transform.SetPositionAndRotation(position, quaternion);
temogo.SetActive(true);
}
//3.池中没有,加载并返回
else
{
temogo = Object.Instantiate(go, position, quaternion);
Add(key, temogo);
}
return temogo;
}
private void Add(string key, GameObject temogo)
{
if (!pool.ContainsKey(key))
{
pool.Add(key, new List<GameObject>());
}
pool[key].Add(temogo);
}
private GameObject FindUseable(string key)
{
if (pool.ContainsKey(key))
{
return pool[key].Find(p => !p.activeSelf);
}
return null;
}
//3.释放资源:从池中删除对象
//3.1释放部分:按key释放
public void Clear(string key)
{
if (pool.ContainsKey(key))
{
for (int i = 0; i < pool[key].Count; i++)
{
Object.Destroy(pool[key][i]);
}
pool.Remove(key);
}
}
//3.2 释放全部
public void ClearAll()
{
foreach (var item in pool.Keys)
{
Clear(item);
}
}
//4.回收对象,使用完对象返回到池中【从画面中消失】
//4.1 即时回收对象
public void CollectObject(GameObject go)
{
go.SetActive(false); //本质:画面小时 设置属性
}
MonoBehaviour mono = new MonoBehaviour();
//4.2 延时回收对象
public void CollectObject(GameObject go, float delay)
{
mono.StartCoroutine(CollectDelay(go, delay));
}
private IEnumerator CollectDelay(GameObject go, float delay)
{
yield return new WaitForSeconds(delay);
CollectObject(go);
}
}
谢谢大家观看