HartoukChartEditor/Assets/Script/Core/BasePool.cs

160 lines
5.8 KiB
C#
Raw Permalink Normal View History

using UnityEngine;
using System.Collections.Generic;
using System;
using System.Collections.ObjectModel;
using System.Linq;
/// <summary>
/// 泛型对象池的父类,支持活跃对象的查找
/// </summary>
/// <typeparam name="BaseClass">基类对象池</typeparam>
public abstract class BasePool<BaseClass> : MonoBehaviour where BaseClass : MonoBehaviour
{
/// <summary>
/// 对象池本体
/// </summary>
protected Dictionary<Type, Stack<BaseClass>> Pools = new Dictionary<Type, Stack<BaseClass>>();
/// <summary>
/// 活跃对象记录表
/// </summary>
protected Dictionary<Type, List<BaseClass>> ActiveObjectList = new Dictionary<Type, List<BaseClass>>();
/// <summary>
/// 依据一个原型,返回一个空的可用对象
/// </summary>
public DerivedClass Get<DerivedClass>(DerivedClass prefab) where DerivedClass : BaseClass
{
var type = typeof(DerivedClass);
if (!Pools.ContainsKey(type))
{
Pools[type] = new Stack<BaseClass>();
ActiveObjectList[type] = new List<BaseClass>();
}
DerivedClass obj;
//对象池逻辑
if (Pools[type].Count > 0)
{
obj = (DerivedClass)Pools[type].Pop();
ActiveObjectList[type].Add(obj);
}
else
{
//如果对象池没有对象,则创建一个对象
obj = Instantiate(prefab);
ActiveObjectList[type].Add(obj);
OnCreate(obj);
}
OnGet(obj);
obj.gameObject.SetActive(true);
obj.enabled = true;
return obj;
}
/// <summary>
/// 回收当前对象
/// </summary>
public void Release(BaseClass Object)
{
var type = Object.GetType();
//如果字典中没有该类的对象池,则创建一个该类型的对象池
if (!Pools.ContainsKey(type)) Pools[type] = new Stack<BaseClass>();
OnRelease(Object);
Object.gameObject.SetActive(false);
Pools[type].Push(Object);
ActiveObjectList[type].Remove(Object);
}
/// <summary>
/// 该对象是否有被实例化
/// </summary>
/// <param name="Object"></param>
/// <returns></returns>
public bool ContainsObject(BaseClass Object)
{
var type = Object.GetType();
//如果没有该类型的对象池,则返回假
if (!Pools.ContainsKey(type)) return false;
return ActiveObjectList[type].Contains(Object);
}
/// <summary>
/// 清空对象池
/// </summary>
/// <remarks>
/// <paramref name="该操作会清空所有的对象"/>
/// </remarks>
public void ClearPool()
{
foreach (var stack in Pools.Values)
{
while (stack.Count > 0)
{
Destroy(stack.Pop().gameObject);
}
}
Pools.Clear();
}
/// <summary>
/// 返回一个当前类型的只读列表
/// </summary>
public ReadOnlyCollection<DerivedClass> GetActiveObjectList<DerivedClass>() where DerivedClass : BaseClass
{
var type=typeof(DerivedClass);
if (!Pools.ContainsKey(type))
{
ActiveObjectList[type] = new List<BaseClass>();
}
//what the fuck ? this code is SHIT!
return ActiveObjectList[type].Cast<DerivedClass>().ToList().AsReadOnly();
}
/// <summary>
/// 对指定类型的所有活跃对象执行指定操作
/// </summary>
/// <typeparam name="DerivedClass">要操作的派生类型</typeparam>
/// <param name="action">要对每个对象执行的操作</param>
/// <param name="includeInactive">是否包含非活跃对象(已回收但未销毁的对象)</param>
public void ForEach<DerivedClass>(Action<DerivedClass> action) where DerivedClass : BaseClass
{
var type = typeof(DerivedClass);
// 检查是否有该类型的活跃对象列表
if (!ActiveObjectList.TryGetValue(type, out var list) || list == null) return;
for (int i = list.Count - 1; i >= 0; i--)
{
var item = (DerivedClass)list[i];
action?.Invoke(item);
}
}
/// <summary>
/// 当对象首次创建时调用
/// </summary>
protected virtual void OnCreate(BaseClass obj) { }
/// <summary>
/// 当对象从池中取出时调用
/// </summary>
protected virtual void OnGet(BaseClass obj) { }
/// <summary>
/// 当对象回收到池中时调用
/// </summary>
protected virtual void OnRelease(BaseClass obj) { }
}
/*
MonoBehaviour
MonoBehaviour可以被转换为任意我们已有的脚本
使unity相关的APISetActive(false)
/
Action()Action()
Action()
仿
*/