GameFramework是一个结构很优秀的Unity游戏框架,但意图似乎在构建可跨引擎的框架?对要求不高的小型个人(不专业)开发来说有些设计过度了,但其中的设计精华很值得学习。
首先来说一下其中的ReferencePool
“引用池”,实质是一组自动管理(不需要单独手动创建销毁)的对象池(不包括GameObject等)。
抽取核心代码,并根据个人习惯修改一些命名后,代码如下
public interface IReference
{
// 采用此类进行清理,清理后应当和刚执行new()后创建得到的新对象状态相同
void Clean();
}
IReference 是自定义的一个接口,将需要进行池化存储的类继承此接口,就可以通过引用池来存取
public static class ReferencePool
{
private sealed class ReferenceCollection
{
private readonly Queue<IReference> m_Objects;
private readonly Type m_ReferenceType;
public Type ReferenceType { get { return m_ReferenceType; } }
public int UnusedReferenceCount { get { return m_Objects.Count; } }
public int UsingReferenceCount { get; private set; }
public ReferenceCollection(Type referenceType)
{
m_Objects = new Queue<IReference>();
m_ReferenceType = referenceType;
}
public void Clear()
{
lock (m_Objects)
{
m_Objects.Clear();
}
}
public T Acquire<T>() where T : class, IReference, new()
{
if (typeof(T) != m_ReferenceType)
{
throw new Exception("Wrong Type");
}
UsingReferenceCount++;
lock (m_Objects)
{
if (m_Objects.Count > 0)
{
return m_Objects.Dequeue() as T;
}
}
return new T();
}
public void Release<T>(T obj) where T : class, IReference, new()
{
if (typeof(T) != m_ReferenceType)
{
throw new Exception("Wrong Type");
}
obj.Clean();
lock (m_Objects)
{
if (m_Objects.Contains(obj))
{
throw new Exception("The reference has been released.");
}
m_Objects.Enqueue(obj);
}
UsingReferenceCount--;
}
}
}
ReferenceCollection
是被管理的对象集合(将单词“Reference”替换为“Object”更好理解),即一个通常意义的对象池,提供了获取、释放对象的接口。原代码中一些用于统计、调试的属性被移除(实际在这里UnusedReferenceCount和UsingReferenceCount也可以先移除)
public static class ReferencePool
{
private static readonly Dictionary<Type, ReferenceCollection> s_ReferenceCollections = new Dictionary<Type, ReferenceCollection>();
public static void Clear()
{
lock (s_ReferenceCollections)
{
foreach (var pair in s_ReferenceCollections)
{
pair.Value.Clear();
}
s_ReferenceCollections.Clear();
}
}
public static T Acquire<T>() where T : class, IReference, new()
{
return GetReferenceCollection<T>().Acquire<T>();
}
public static void Release<T>(T obj) where T : class, IReference, new()
{
GetReferenceCollection<T>().Release<T>(obj);
}
private static ReferenceCollection GetReferenceCollection<T>() where T : class, IReference, new()
{
ReferenceCollection referenceCollection = null;
Type type = typeof(T);
lock (s_ReferenceCollections)
{
if (!s_ReferenceCollections.TryGetValue(type, out referenceCollection))
{
referenceCollection = new ReferenceCollection(type);
s_ReferenceCollections.Add(type, referenceCollection);
}
}
return referenceCollection;
}
}
ReferencePool
最终提供了统一的对外接口ReferencePool.Acquire<T>()
和ReferencePool.Release<T>()
在此基础上,可以添加原代码中的添加、删除、获取、释放计数
或设置ReferenceCollection的数量上限,如一个基于GameFramework的框架 HTFramework