彻底重构ObjectPoolService模块
重构ObjectPoolService模块 去掉过度设计移除旧的容器列表 使用自定义Hash提高整体性能速度 单线程高吞吐
This commit is contained in:
parent
a08ef4be2e
commit
e42be670fe
@ -67,26 +67,27 @@ namespace AlicizaX.Editor
|
||||
EditorGUILayout.LabelField("Auto Release Interval", objectPool.AutoReleaseInterval.ToString());
|
||||
EditorGUILayout.LabelField("Capacity", objectPool.Capacity.ToString());
|
||||
EditorGUILayout.LabelField("Used Count", objectPool.Count.ToString());
|
||||
EditorGUILayout.LabelField("Can Release Count", objectPool.CanReleaseCount.ToString());
|
||||
EditorGUILayout.LabelField("Expire Time", objectPool.ExpireTime.ToString());
|
||||
EditorGUILayout.LabelField("Priority", objectPool.Priority.ToString());
|
||||
ObjectInfo[] objectInfos = objectPool.GetAllObjectInfos();
|
||||
if (objectInfos.Length > 0)
|
||||
{
|
||||
EditorGUILayout.LabelField("Name", objectPool.AllowMultiSpawn ? "Locked\tCount\tFlag\tPriority\tLast Use Time" : "Locked\tIn Use\tFlag\tPriority\tLast Use Time");
|
||||
EditorGUILayout.LabelField("Name", objectPool.AllowMultiSpawn ? "Locked\tCount\tFlag\tLast Use Time" : "Locked\tIn Use\tFlag\tLast Use Time");
|
||||
foreach (ObjectInfo objectInfo in objectInfos)
|
||||
{
|
||||
#if UNITY_6000_0_OR_NEWER
|
||||
|
||||
string lastUse = Utility.Text.Format("{0:F1}s ago", UnityEngine.Time.realtimeSinceStartup - objectInfo.LastUseTime);
|
||||
EditorGUILayout.LabelField(string.IsNullOrEmpty(objectInfo.Name) ? "<None>" : objectInfo.Name,
|
||||
objectPool.AllowMultiSpawn
|
||||
? Utility.Text.Format("{0,-12}\t{1,-12}\t{2,-12}\t{3,-12}\t{4:yyyy-MM-dd HH:mm:ss,-12}", objectInfo.Locked, objectInfo.SpawnCount, objectInfo.CustomCanReleaseFlag, objectInfo.Priority, objectInfo.LastUseTime.ToLocalTime())
|
||||
: Utility.Text.Format("{0,-12}\t{1,-12}\t{2,-12}\t{3,-12}\t{4:yyyy-MM-dd HH:mm:ss,-12}", objectInfo.Locked, objectInfo.IsInUse, objectInfo.CustomCanReleaseFlag, objectInfo.Priority, objectInfo.LastUseTime.ToLocalTime()));
|
||||
? Utility.Text.Format("{0,-12}\t{1,-12}\t{2,-12}\t{3,-12}", objectInfo.Locked, objectInfo.SpawnCount, objectInfo.CustomCanReleaseFlag, lastUse)
|
||||
: Utility.Text.Format("{0,-12}\t{1,-12}\t{2,-12}\t{3,-12}", objectInfo.Locked, objectInfo.IsInUse, objectInfo.CustomCanReleaseFlag, lastUse));
|
||||
#else
|
||||
EditorGUILayout.LabelField(string.IsNullOrEmpty(objectInfo.Name) ? "<None>" : objectInfo.Name,
|
||||
string lastUse = Utility.Text.Format("{0:F1}s ago", UnityEngine.Time.realtimeSinceStartup - objectInfo.LastUseTime);
|
||||
EditorGUILayout.LabelField(string.IsNullOrEmpty(objectInfo.Name) ? "<None>" : objectInfo.Name,
|
||||
objectPool.AllowMultiSpawn
|
||||
? Utility.Text.Format("{0}\t{1}\t{2}\t{3}\t{4:yyyy-MM-dd HH:mm:ss}", objectInfo.Locked, objectInfo.SpawnCount, objectInfo.CustomCanReleaseFlag, objectInfo.Priority, objectInfo.LastUseTime.ToLocalTime())
|
||||
: Utility.Text.Format("{0}\t{1}\t{2}\t{3}\t{4:yyyy-MM-dd HH:mm:ss}", objectInfo.Locked, objectInfo.IsInUse, objectInfo.CustomCanReleaseFlag, objectInfo.Priority, objectInfo.LastUseTime.ToLocalTime()));
|
||||
? Utility.Text.Format("{0}\t{1}\t{2}\t{3}", objectInfo.Locked, objectInfo.SpawnCount, objectInfo.CustomCanReleaseFlag, lastUse)
|
||||
: Utility.Text.Format("{0}\t{1}\t{2}\t{3}", objectInfo.Locked, objectInfo.IsInUse, objectInfo.CustomCanReleaseFlag, lastUse));
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -109,12 +110,13 @@ namespace AlicizaX.Editor
|
||||
{
|
||||
int index = 0;
|
||||
string[] data = new string[objectInfos.Length + 1];
|
||||
data[index++] = Utility.Text.Format("Name,Locked,{0},Custom Can Release Flag,Priority,Last Use Time", objectPool.AllowMultiSpawn ? "Count" : "In Use");
|
||||
data[index++] = Utility.Text.Format("Name,Locked,{0},Custom Can Release Flag,Last Use Time", objectPool.AllowMultiSpawn ? "Count" : "In Use");
|
||||
foreach (ObjectInfo objectInfo in objectInfos)
|
||||
{
|
||||
string csvLastUse = Utility.Text.Format("{0:F1}s ago", UnityEngine.Time.realtimeSinceStartup - objectInfo.LastUseTime);
|
||||
data[index++] = objectPool.AllowMultiSpawn
|
||||
? Utility.Text.Format("{0},{1},{2},{3},{4},{5:yyyy-MM-dd HH:mm:ss}", objectInfo.Name, objectInfo.Locked, objectInfo.SpawnCount, objectInfo.CustomCanReleaseFlag, objectInfo.Priority, objectInfo.LastUseTime.ToLocalTime())
|
||||
: Utility.Text.Format("{0},{1},{2},{3},{4},{5:yyyy-MM-dd HH:mm:ss}", objectInfo.Name, objectInfo.Locked, objectInfo.IsInUse, objectInfo.CustomCanReleaseFlag, objectInfo.Priority, objectInfo.LastUseTime.ToLocalTime());
|
||||
? Utility.Text.Format("{0},{1},{2},{3},{4}", objectInfo.Name, objectInfo.Locked, objectInfo.SpawnCount, objectInfo.CustomCanReleaseFlag, csvLastUse)
|
||||
: Utility.Text.Format("{0},{1},{2},{3},{4}", objectInfo.Name, objectInfo.Locked, objectInfo.IsInUse, objectInfo.CustomCanReleaseFlag, csvLastUse);
|
||||
}
|
||||
|
||||
File.WriteAllLines(exportFileName, data, Encoding.UTF8);
|
||||
|
||||
@ -1,456 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace AlicizaX
|
||||
{
|
||||
/// <summary>
|
||||
/// 游戏框架链表类。
|
||||
/// </summary>
|
||||
/// <typeparam name="T">指定链表的元素类型。</typeparam>
|
||||
public sealed class GameFrameworkLinkedList<T> : ICollection<T>, IEnumerable<T>, ICollection, IEnumerable
|
||||
{
|
||||
private readonly LinkedList<T> m_LinkedList;
|
||||
private readonly Queue<LinkedListNode<T>> m_CachedNodes;
|
||||
|
||||
/// <summary>
|
||||
/// 初始化游戏框架链表类的新实例。
|
||||
/// </summary>
|
||||
public GameFrameworkLinkedList()
|
||||
{
|
||||
m_LinkedList = new LinkedList<T>();
|
||||
m_CachedNodes = new Queue<LinkedListNode<T>>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取链表中实际包含的结点数量。
|
||||
/// </summary>
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_LinkedList.Count;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取链表结点缓存数量。
|
||||
/// </summary>
|
||||
public int CachedNodeCount
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_CachedNodes.Count;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取链表的第一个结点。
|
||||
/// </summary>
|
||||
public LinkedListNode<T> First
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_LinkedList.First;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取链表的最后一个结点。
|
||||
/// </summary>
|
||||
public LinkedListNode<T> Last
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_LinkedList.Last;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取一个值,该值指示 ICollection`1 是否为只读。
|
||||
/// </summary>
|
||||
public bool IsReadOnly
|
||||
{
|
||||
get
|
||||
{
|
||||
return ((ICollection<T>)m_LinkedList).IsReadOnly;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取可用于同步对 ICollection 的访问的对象。
|
||||
/// </summary>
|
||||
public object SyncRoot
|
||||
{
|
||||
get
|
||||
{
|
||||
return ((ICollection)m_LinkedList).SyncRoot;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取一个值,该值指示是否同步对 ICollection 的访问(线程安全)。
|
||||
/// </summary>
|
||||
public bool IsSynchronized
|
||||
{
|
||||
get
|
||||
{
|
||||
return ((ICollection)m_LinkedList).IsSynchronized;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在链表中指定的现有结点后添加包含指定值的新结点。
|
||||
/// </summary>
|
||||
/// <param name="node">指定的现有结点。</param>
|
||||
/// <param name="value">指定值。</param>
|
||||
/// <returns>包含指定值的新结点。</returns>
|
||||
public LinkedListNode<T> AddAfter(LinkedListNode<T> node, T value)
|
||||
{
|
||||
LinkedListNode<T> newNode = AcquireNode(value);
|
||||
m_LinkedList.AddAfter(node, newNode);
|
||||
return newNode;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在链表中指定的现有结点后添加指定的新结点。
|
||||
/// </summary>
|
||||
/// <param name="node">指定的现有结点。</param>
|
||||
/// <param name="newNode">指定的新结点。</param>
|
||||
public void AddAfter(LinkedListNode<T> node, LinkedListNode<T> newNode)
|
||||
{
|
||||
m_LinkedList.AddAfter(node, newNode);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在链表中指定的现有结点前添加包含指定值的新结点。
|
||||
/// </summary>
|
||||
/// <param name="node">指定的现有结点。</param>
|
||||
/// <param name="value">指定值。</param>
|
||||
/// <returns>包含指定值的新结点。</returns>
|
||||
public LinkedListNode<T> AddBefore(LinkedListNode<T> node, T value)
|
||||
{
|
||||
LinkedListNode<T> newNode = AcquireNode(value);
|
||||
m_LinkedList.AddBefore(node, newNode);
|
||||
return newNode;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在链表中指定的现有结点前添加指定的新结点。
|
||||
/// </summary>
|
||||
/// <param name="node">指定的现有结点。</param>
|
||||
/// <param name="newNode">指定的新结点。</param>
|
||||
public void AddBefore(LinkedListNode<T> node, LinkedListNode<T> newNode)
|
||||
{
|
||||
m_LinkedList.AddBefore(node, newNode);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在链表的开头处添加包含指定值的新结点。
|
||||
/// </summary>
|
||||
/// <param name="value">指定值。</param>
|
||||
/// <returns>包含指定值的新结点。</returns>
|
||||
public LinkedListNode<T> AddFirst(T value)
|
||||
{
|
||||
LinkedListNode<T> node = AcquireNode(value);
|
||||
m_LinkedList.AddFirst(node);
|
||||
return node;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在链表的开头处添加指定的新结点。
|
||||
/// </summary>
|
||||
/// <param name="node">指定的新结点。</param>
|
||||
public void AddFirst(LinkedListNode<T> node)
|
||||
{
|
||||
m_LinkedList.AddFirst(node);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在链表的结尾处添加包含指定值的新结点。
|
||||
/// </summary>
|
||||
/// <param name="value">指定值。</param>
|
||||
/// <returns>包含指定值的新结点。</returns>
|
||||
public LinkedListNode<T> AddLast(T value)
|
||||
{
|
||||
LinkedListNode<T> node = AcquireNode(value);
|
||||
m_LinkedList.AddLast(node);
|
||||
return node;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在链表的结尾处添加指定的新结点。
|
||||
/// </summary>
|
||||
/// <param name="node">指定的新结点。</param>
|
||||
public void AddLast(LinkedListNode<T> node)
|
||||
{
|
||||
m_LinkedList.AddLast(node);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从链表中移除所有结点。
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
LinkedListNode<T> current = m_LinkedList.First;
|
||||
while (current != null)
|
||||
{
|
||||
ReleaseNode(current);
|
||||
current = current.Next;
|
||||
}
|
||||
|
||||
m_LinkedList.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清除链表结点缓存。
|
||||
/// </summary>
|
||||
public void ClearCachedNodes()
|
||||
{
|
||||
m_CachedNodes.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 确定某值是否在链表中。
|
||||
/// </summary>
|
||||
/// <param name="value">指定值。</param>
|
||||
/// <returns>某值是否在链表中。</returns>
|
||||
public bool Contains(T value)
|
||||
{
|
||||
return m_LinkedList.Contains(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 确定指定结点是否在链表中。
|
||||
/// </summary>
|
||||
/// <param name="node">要检查的结点。</param>
|
||||
/// <returns>指定结点是否在链表中。</returns>
|
||||
public bool Contains(LinkedListNode<T> node)
|
||||
{
|
||||
return node != null && node.List == m_LinkedList;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从目标数组的指定索引处开始将整个链表复制到兼容的一维数组。
|
||||
/// </summary>
|
||||
/// <param name="array">一维数组,它是从链表复制的元素的目标。数组必须具有从零开始的索引。</param>
|
||||
/// <param name="index">array 中从零开始的索引,从此处开始复制。</param>
|
||||
public void CopyTo(T[] array, int index)
|
||||
{
|
||||
m_LinkedList.CopyTo(array, index);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从特定的 ICollection 索引开始,将数组的元素复制到一个数组中。
|
||||
/// </summary>
|
||||
/// <param name="array">一维数组,它是从 ICollection 复制的元素的目标。数组必须具有从零开始的索引。</param>
|
||||
/// <param name="index">array 中从零开始的索引,从此处开始复制。</param>
|
||||
public void CopyTo(Array array, int index)
|
||||
{
|
||||
((ICollection)m_LinkedList).CopyTo(array, index);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找包含指定值的第一个结点。
|
||||
/// </summary>
|
||||
/// <param name="value">要查找的指定值。</param>
|
||||
/// <returns>包含指定值的第一个结点。</returns>
|
||||
public LinkedListNode<T> Find(T value)
|
||||
{
|
||||
return m_LinkedList.Find(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找包含指定值的最后一个结点。
|
||||
/// </summary>
|
||||
/// <param name="value">要查找的指定值。</param>
|
||||
/// <returns>包含指定值的最后一个结点。</returns>
|
||||
public LinkedListNode<T> FindLast(T value)
|
||||
{
|
||||
return m_LinkedList.FindLast(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从链表中移除指定值的第一个匹配项。
|
||||
/// </summary>
|
||||
/// <param name="value">指定值。</param>
|
||||
/// <returns>是否移除成功。</returns>
|
||||
public bool Remove(T value)
|
||||
{
|
||||
LinkedListNode<T> node = m_LinkedList.Find(value);
|
||||
if (node != null)
|
||||
{
|
||||
m_LinkedList.Remove(node);
|
||||
ReleaseNode(node);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从链表中移除指定的结点。
|
||||
/// </summary>
|
||||
/// <param name="node">指定的结点。</param>
|
||||
public void Remove(LinkedListNode<T> node)
|
||||
{
|
||||
m_LinkedList.Remove(node);
|
||||
ReleaseNode(node);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 移除位于链表开头处的结点。
|
||||
/// </summary>
|
||||
public void RemoveFirst()
|
||||
{
|
||||
LinkedListNode<T> first = m_LinkedList.First;
|
||||
if (first == null)
|
||||
{
|
||||
throw new GameFrameworkException("First is invalid.");
|
||||
}
|
||||
|
||||
m_LinkedList.RemoveFirst();
|
||||
ReleaseNode(first);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 移除位于链表结尾处的结点。
|
||||
/// </summary>
|
||||
public void RemoveLast()
|
||||
{
|
||||
LinkedListNode<T> last = m_LinkedList.Last;
|
||||
if (last == null)
|
||||
{
|
||||
throw new GameFrameworkException("Last is invalid.");
|
||||
}
|
||||
|
||||
m_LinkedList.RemoveLast();
|
||||
ReleaseNode(last);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 返回循环访问集合的枚举数。
|
||||
/// </summary>
|
||||
/// <returns>循环访问集合的枚举数。</returns>
|
||||
public Enumerator GetEnumerator()
|
||||
{
|
||||
return new Enumerator(m_LinkedList);
|
||||
}
|
||||
|
||||
private LinkedListNode<T> AcquireNode(T value)
|
||||
{
|
||||
LinkedListNode<T> node = null;
|
||||
if (m_CachedNodes.Count > 0)
|
||||
{
|
||||
node = m_CachedNodes.Dequeue();
|
||||
node.Value = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
node = new LinkedListNode<T>(value);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
private void ReleaseNode(LinkedListNode<T> node)
|
||||
{
|
||||
node.Value = default(T);
|
||||
m_CachedNodes.Enqueue(node);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将值添加到 ICollection`1 的结尾处。
|
||||
/// </summary>
|
||||
/// <param name="value">要添加的值。</param>
|
||||
void ICollection<T>.Add(T value)
|
||||
{
|
||||
AddLast(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 返回循环访问集合的枚举数。
|
||||
/// </summary>
|
||||
/// <returns>循环访问集合的枚举数。</returns>
|
||||
IEnumerator<T> IEnumerable<T>.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 返回循环访问集合的枚举数。
|
||||
/// </summary>
|
||||
/// <returns>循环访问集合的枚举数。</returns>
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 循环访问集合的枚举数。
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Auto)]
|
||||
public struct Enumerator : IEnumerator<T>, IEnumerator
|
||||
{
|
||||
private LinkedList<T>.Enumerator m_Enumerator;
|
||||
|
||||
internal Enumerator(LinkedList<T> linkedList)
|
||||
{
|
||||
if (linkedList == null)
|
||||
{
|
||||
throw new GameFrameworkException("Linked list is invalid.");
|
||||
}
|
||||
|
||||
m_Enumerator = linkedList.GetEnumerator();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前结点。
|
||||
/// </summary>
|
||||
public T Current
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Enumerator.Current;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前的枚举数。
|
||||
/// </summary>
|
||||
object IEnumerator.Current
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Enumerator.Current;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清理枚举数。
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
m_Enumerator.Dispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取下一个结点。
|
||||
/// </summary>
|
||||
/// <returns>返回下一个结点。</returns>
|
||||
public bool MoveNext()
|
||||
{
|
||||
return m_Enumerator.MoveNext();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重置枚举数。
|
||||
/// </summary>
|
||||
void IEnumerator.Reset()
|
||||
{
|
||||
((IEnumerator<T>)m_Enumerator).Reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8662d2b0651bb46308fa9ea5a24a9f08
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -1,210 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace AlicizaX
|
||||
{
|
||||
/// <summary>
|
||||
/// 游戏框架链表范围。
|
||||
/// </summary>
|
||||
/// <typeparam name="T">指定链表范围的元素类型。</typeparam>
|
||||
[StructLayout(LayoutKind.Auto)]
|
||||
public readonly struct GameFrameworkLinkedListRange<T> : IEnumerable<T>, IEnumerable
|
||||
{
|
||||
private readonly LinkedListNode<T> m_First;
|
||||
private readonly LinkedListNode<T> m_Terminal;
|
||||
|
||||
/// <summary>
|
||||
/// 初始化游戏框架链表范围的新实例。
|
||||
/// </summary>
|
||||
/// <param name="first">链表范围的开始结点。</param>
|
||||
/// <param name="terminal">链表范围的终结标记结点。</param>
|
||||
public GameFrameworkLinkedListRange(LinkedListNode<T> first, LinkedListNode<T> terminal)
|
||||
{
|
||||
if (first == null || terminal == null || first == terminal)
|
||||
{
|
||||
throw new GameFrameworkException("Range is invalid.");
|
||||
}
|
||||
|
||||
m_First = first;
|
||||
m_Terminal = terminal;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取链表范围是否有效。
|
||||
/// </summary>
|
||||
public bool IsValid
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_First != null && m_Terminal != null && m_First != m_Terminal;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取链表范围的开始结点。
|
||||
/// </summary>
|
||||
public LinkedListNode<T> First
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_First;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取链表范围的终结标记结点。
|
||||
/// </summary>
|
||||
public LinkedListNode<T> Terminal
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Terminal;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取链表范围的结点数量。
|
||||
/// </summary>
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!IsValid)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
for (LinkedListNode<T> current = m_First; current != null && current != m_Terminal; current = current.Next)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查是否包含指定值。
|
||||
/// </summary>
|
||||
/// <param name="value">要检查的值。</param>
|
||||
/// <returns>是否包含指定值。</returns>
|
||||
public bool Contains(T value)
|
||||
{
|
||||
for (LinkedListNode<T> current = m_First; current != null && current != m_Terminal; current = current.Next)
|
||||
{
|
||||
if (current.Value.Equals(value))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 返回循环访问集合的枚举数。
|
||||
/// </summary>
|
||||
/// <returns>循环访问集合的枚举数。</returns>
|
||||
public Enumerator GetEnumerator()
|
||||
{
|
||||
return new Enumerator(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 返回循环访问集合的枚举数。
|
||||
/// </summary>
|
||||
/// <returns>循环访问集合的枚举数。</returns>
|
||||
IEnumerator<T> IEnumerable<T>.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 返回循环访问集合的枚举数。
|
||||
/// </summary>
|
||||
/// <returns>循环访问集合的枚举数。</returns>
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 循环访问集合的枚举数。
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Auto)]
|
||||
public struct Enumerator : IEnumerator<T>, IEnumerator
|
||||
{
|
||||
private readonly GameFrameworkLinkedListRange<T> m_GameFrameworkLinkedListRange;
|
||||
private LinkedListNode<T> m_Current;
|
||||
private T m_CurrentValue;
|
||||
|
||||
internal Enumerator(GameFrameworkLinkedListRange<T> range)
|
||||
{
|
||||
if (!range.IsValid)
|
||||
{
|
||||
throw new GameFrameworkException("Range is invalid.");
|
||||
}
|
||||
|
||||
m_GameFrameworkLinkedListRange = range;
|
||||
m_Current = m_GameFrameworkLinkedListRange.m_First;
|
||||
m_CurrentValue = default(T);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前结点。
|
||||
/// </summary>
|
||||
public T Current
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_CurrentValue;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前的枚举数。
|
||||
/// </summary>
|
||||
object IEnumerator.Current
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_CurrentValue;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清理枚举数。
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取下一个结点。
|
||||
/// </summary>
|
||||
/// <returns>返回下一个结点。</returns>
|
||||
public bool MoveNext()
|
||||
{
|
||||
if (m_Current == null || m_Current == m_GameFrameworkLinkedListRange.m_Terminal)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_CurrentValue = m_Current.Value;
|
||||
m_Current = m_Current.Next;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重置枚举数。
|
||||
/// </summary>
|
||||
void IEnumerator.Reset()
|
||||
{
|
||||
m_Current = m_GameFrameworkLinkedListRange.m_First;
|
||||
m_CurrentValue = default(T);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7edbebe0b1fd848418e2f1d863b611e1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -1,304 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace AlicizaX
|
||||
{
|
||||
/// <summary>
|
||||
/// 游戏框架多值字典类。
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey">指定多值字典的主键类型。</typeparam>
|
||||
/// <typeparam name="TValue">指定多值字典的值类型。</typeparam>
|
||||
public sealed class GameFrameworkMultiDictionary<TKey, TValue> : IEnumerable<KeyValuePair<TKey, GameFrameworkLinkedListRange<TValue>>>, IEnumerable
|
||||
{
|
||||
private readonly GameFrameworkLinkedList<TValue> m_LinkedList;
|
||||
private readonly Dictionary<TKey, GameFrameworkLinkedListRange<TValue>> m_Dictionary;
|
||||
|
||||
/// <summary>
|
||||
/// 初始化游戏框架多值字典类的新实例。
|
||||
/// </summary>
|
||||
public GameFrameworkMultiDictionary()
|
||||
{
|
||||
m_LinkedList = new GameFrameworkLinkedList<TValue>();
|
||||
m_Dictionary = new Dictionary<TKey, GameFrameworkLinkedListRange<TValue>>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取多值字典中实际包含的主键数量。
|
||||
/// </summary>
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Dictionary.Count;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取多值字典中指定主键的范围。
|
||||
/// </summary>
|
||||
/// <param name="key">指定的主键。</param>
|
||||
/// <returns>指定主键的范围。</returns>
|
||||
public GameFrameworkLinkedListRange<TValue> this[TKey key]
|
||||
{
|
||||
get
|
||||
{
|
||||
GameFrameworkLinkedListRange<TValue> range = default(GameFrameworkLinkedListRange<TValue>);
|
||||
m_Dictionary.TryGetValue(key, out range);
|
||||
return range;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清理多值字典。
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
m_Dictionary.Clear();
|
||||
m_LinkedList.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查多值字典中是否包含指定主键。
|
||||
/// </summary>
|
||||
/// <param name="key">要检查的主键。</param>
|
||||
/// <returns>多值字典中是否包含指定主键。</returns>
|
||||
public bool Contains(TKey key)
|
||||
{
|
||||
return m_Dictionary.ContainsKey(key);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查多值字典中是否包含指定值。
|
||||
/// </summary>
|
||||
/// <param name="key">要检查的主键。</param>
|
||||
/// <param name="value">要检查的值。</param>
|
||||
/// <returns>多值字典中是否包含指定值。</returns>
|
||||
public bool Contains(TKey key, TValue value)
|
||||
{
|
||||
GameFrameworkLinkedListRange<TValue> range = default(GameFrameworkLinkedListRange<TValue>);
|
||||
if (m_Dictionary.TryGetValue(key, out range))
|
||||
{
|
||||
return range.Contains(value);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 尝试获取多值字典中指定主键的范围。
|
||||
/// </summary>
|
||||
/// <param name="key">指定的主键。</param>
|
||||
/// <param name="range">指定主键的范围。</param>
|
||||
/// <returns>是否获取成功。</returns>
|
||||
public bool TryGetValue(TKey key, out GameFrameworkLinkedListRange<TValue> range)
|
||||
{
|
||||
return m_Dictionary.TryGetValue(key, out range);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 向指定的主键增加指定的值。
|
||||
/// </summary>
|
||||
/// <param name="key">指定的主键。</param>
|
||||
/// <param name="value">指定的值。</param>
|
||||
public LinkedListNode<TValue> Add(TKey key, TValue value)
|
||||
{
|
||||
GameFrameworkLinkedListRange<TValue> range = default(GameFrameworkLinkedListRange<TValue>);
|
||||
if (m_Dictionary.TryGetValue(key, out range))
|
||||
{
|
||||
return m_LinkedList.AddBefore(range.Terminal, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
LinkedListNode<TValue> first = m_LinkedList.AddLast(value);
|
||||
LinkedListNode<TValue> terminal = m_LinkedList.AddLast(default(TValue));
|
||||
m_Dictionary.Add(key, new GameFrameworkLinkedListRange<TValue>(first, terminal));
|
||||
return first;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从指定的主键中移除指定的值。
|
||||
/// </summary>
|
||||
/// <param name="key">指定的主键。</param>
|
||||
/// <param name="value">指定的值。</param>
|
||||
/// <returns>是否移除成功。</returns>
|
||||
public bool Remove(TKey key, TValue value)
|
||||
{
|
||||
GameFrameworkLinkedListRange<TValue> range = default(GameFrameworkLinkedListRange<TValue>);
|
||||
if (m_Dictionary.TryGetValue(key, out range))
|
||||
{
|
||||
for (LinkedListNode<TValue> current = range.First; current != null && current != range.Terminal; current = current.Next)
|
||||
{
|
||||
if (current.Value.Equals(value))
|
||||
{
|
||||
return Remove(key, current);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从指定的主键中移除指定结点。
|
||||
/// </summary>
|
||||
/// <param name="key">指定的主键。</param>
|
||||
/// <param name="node">要移除的结点。</param>
|
||||
/// <returns>是否移除成功。</returns>
|
||||
public bool Remove(TKey key, LinkedListNode<TValue> node)
|
||||
{
|
||||
if (node == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
GameFrameworkLinkedListRange<TValue> range = default(GameFrameworkLinkedListRange<TValue>);
|
||||
if (!m_Dictionary.TryGetValue(key, out range))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_LinkedList.Contains(node) || node == range.Terminal)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (node == range.First)
|
||||
{
|
||||
LinkedListNode<TValue> next = node.Next;
|
||||
if (next == range.Terminal)
|
||||
{
|
||||
m_LinkedList.Remove(next);
|
||||
m_Dictionary.Remove(key);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Dictionary[key] = new GameFrameworkLinkedListRange<TValue>(next, range.Terminal);
|
||||
}
|
||||
}
|
||||
|
||||
m_LinkedList.Remove(node);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从指定的主键中移除所有的值。
|
||||
/// </summary>
|
||||
/// <param name="key">指定的主键。</param>
|
||||
/// <returns>是否移除成功。</returns>
|
||||
public bool RemoveAll(TKey key)
|
||||
{
|
||||
GameFrameworkLinkedListRange<TValue> range = default(GameFrameworkLinkedListRange<TValue>);
|
||||
if (m_Dictionary.TryGetValue(key, out range))
|
||||
{
|
||||
m_Dictionary.Remove(key);
|
||||
|
||||
LinkedListNode<TValue> current = range.First;
|
||||
while (current != null)
|
||||
{
|
||||
LinkedListNode<TValue> next = current != range.Terminal ? current.Next : null;
|
||||
m_LinkedList.Remove(current);
|
||||
current = next;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 返回循环访问集合的枚举数。
|
||||
/// </summary>
|
||||
/// <returns>循环访问集合的枚举数。</returns>
|
||||
public Enumerator GetEnumerator()
|
||||
{
|
||||
return new Enumerator(m_Dictionary);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 返回循环访问集合的枚举数。
|
||||
/// </summary>
|
||||
/// <returns>循环访问集合的枚举数。</returns>
|
||||
IEnumerator<KeyValuePair<TKey, GameFrameworkLinkedListRange<TValue>>> IEnumerable<KeyValuePair<TKey, GameFrameworkLinkedListRange<TValue>>>.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 返回循环访问集合的枚举数。
|
||||
/// </summary>
|
||||
/// <returns>循环访问集合的枚举数。</returns>
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 循环访问集合的枚举数。
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Auto)]
|
||||
public struct Enumerator : IEnumerator<KeyValuePair<TKey, GameFrameworkLinkedListRange<TValue>>>, IEnumerator
|
||||
{
|
||||
private Dictionary<TKey, GameFrameworkLinkedListRange<TValue>>.Enumerator m_Enumerator;
|
||||
|
||||
internal Enumerator(Dictionary<TKey, GameFrameworkLinkedListRange<TValue>> dictionary)
|
||||
{
|
||||
if (dictionary == null)
|
||||
{
|
||||
throw new GameFrameworkException("Dictionary is invalid.");
|
||||
}
|
||||
|
||||
m_Enumerator = dictionary.GetEnumerator();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前结点。
|
||||
/// </summary>
|
||||
public KeyValuePair<TKey, GameFrameworkLinkedListRange<TValue>> Current
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Enumerator.Current;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前的枚举数。
|
||||
/// </summary>
|
||||
object IEnumerator.Current
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Enumerator.Current;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清理枚举数。
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
m_Enumerator.Dispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取下一个结点。
|
||||
/// </summary>
|
||||
/// <returns>返回下一个结点。</returns>
|
||||
public bool MoveNext()
|
||||
{
|
||||
return m_Enumerator.MoveNext();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重置枚举数。
|
||||
/// </summary>
|
||||
void IEnumerator.Reset()
|
||||
{
|
||||
((IEnumerator<KeyValuePair<TKey, GameFrameworkLinkedListRange<TValue>>>)m_Enumerator).Reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,199 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace AlicizaX
|
||||
{
|
||||
/// <summary>
|
||||
/// 游戏框架序列化器基类。
|
||||
/// </summary>
|
||||
/// <typeparam name="T">要序列化的数据类型。</typeparam>
|
||||
public abstract class GameFrameworkSerializer<T>
|
||||
{
|
||||
private readonly Dictionary<byte, SerializeCallback> _serializeCallbacks;
|
||||
private readonly Dictionary<byte, DeserializeCallback> _deserializeCallbacks;
|
||||
private readonly Dictionary<byte, TryGetValueCallback> _tryGetValueCallbacks;
|
||||
private byte _latestSerializeCallbackVersion;
|
||||
|
||||
/// <summary>
|
||||
/// 初始化游戏框架序列化器基类的新实例。
|
||||
/// </summary>
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
public GameFrameworkSerializer()
|
||||
{
|
||||
_serializeCallbacks = new Dictionary<byte, SerializeCallback>();
|
||||
_deserializeCallbacks = new Dictionary<byte, DeserializeCallback>();
|
||||
_tryGetValueCallbacks = new Dictionary<byte, TryGetValueCallback>();
|
||||
_latestSerializeCallbackVersion = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 序列化回调函数。
|
||||
/// </summary>
|
||||
/// <param name="stream">目标流。</param>
|
||||
/// <param name="data">要序列化的数据。</param>
|
||||
/// <returns>是否序列化数据成功。</returns>
|
||||
public delegate bool SerializeCallback(Stream stream, T data);
|
||||
|
||||
/// <summary>
|
||||
/// 反序列化回调函数。
|
||||
/// </summary>
|
||||
/// <param name="stream">指定流。</param>
|
||||
/// <returns>反序列化的数据。</returns>
|
||||
public delegate T DeserializeCallback(Stream stream);
|
||||
|
||||
/// <summary>
|
||||
/// 尝试从指定流获取指定键的值回调函数。
|
||||
/// </summary>
|
||||
/// <param name="stream">指定流。</param>
|
||||
/// <param name="key">指定键。</param>
|
||||
/// <param name="value">指定键的值。</param>
|
||||
/// <returns>是否从指定流获取指定键的值成功。</returns>
|
||||
public delegate bool TryGetValueCallback(Stream stream, string key, out object value);
|
||||
|
||||
/// <summary>
|
||||
/// 注册序列化回调函数。
|
||||
/// </summary>
|
||||
/// <param name="version">序列化回调函数的版本。</param>
|
||||
/// <param name="callback">序列化回调函数。</param>
|
||||
public void RegisterSerializeCallback(byte version, SerializeCallback callback)
|
||||
{
|
||||
if (callback == null)
|
||||
{
|
||||
throw new GameFrameworkException("Serialize callback is invalid.");
|
||||
}
|
||||
|
||||
_serializeCallbacks[version] = callback;
|
||||
if (version > _latestSerializeCallbackVersion)
|
||||
{
|
||||
_latestSerializeCallbackVersion = version;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 注册反序列化回调函数。
|
||||
/// </summary>
|
||||
/// <param name="version">反序列化回调函数的版本。</param>
|
||||
/// <param name="callback">反序列化回调函数。</param>
|
||||
public void RegisterDeserializeCallback(byte version, DeserializeCallback callback)
|
||||
{
|
||||
if (callback == null)
|
||||
{
|
||||
throw new GameFrameworkException("Deserialize callback is invalid.");
|
||||
}
|
||||
|
||||
_deserializeCallbacks[version] = callback;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 注册尝试从指定流获取指定键的值回调函数。
|
||||
/// </summary>
|
||||
/// <param name="version">尝试从指定流获取指定键的值回调函数的版本。</param>
|
||||
/// <param name="callback">尝试从指定流获取指定键的值回调函数。</param>
|
||||
public void RegisterTryGetValueCallback(byte version, TryGetValueCallback callback)
|
||||
{
|
||||
if (callback == null)
|
||||
{
|
||||
throw new GameFrameworkException("Try get value callback is invalid.");
|
||||
}
|
||||
|
||||
_tryGetValueCallbacks[version] = callback;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 序列化数据到目标流中。
|
||||
/// </summary>
|
||||
/// <param name="stream">目标流。</param>
|
||||
/// <param name="data">要序列化的数据。</param>
|
||||
/// <returns>是否序列化数据成功。</returns>
|
||||
public bool Serialize(Stream stream, T data)
|
||||
{
|
||||
if (_serializeCallbacks.Count <= 0)
|
||||
{
|
||||
throw new GameFrameworkException("No serialize callback registered.");
|
||||
}
|
||||
|
||||
return Serialize(stream, data, _latestSerializeCallbackVersion);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 序列化数据到目标流中。
|
||||
/// </summary>
|
||||
/// <param name="stream">目标流。</param>
|
||||
/// <param name="data">要序列化的数据。</param>
|
||||
/// <param name="version">序列化回调函数的版本。</param>
|
||||
/// <returns>是否序列化数据成功。</returns>
|
||||
public bool Serialize(Stream stream, T data, byte version)
|
||||
{
|
||||
byte[] header = GetHeader();
|
||||
stream.WriteByte(header[0]);
|
||||
stream.WriteByte(header[1]);
|
||||
stream.WriteByte(header[2]);
|
||||
stream.WriteByte(version);
|
||||
if (!_serializeCallbacks.TryGetValue(version, out var callback))
|
||||
{
|
||||
throw new GameFrameworkException(Utility.Text.Format("Serialize callback '{0}' is not exist.", version));
|
||||
}
|
||||
|
||||
return callback(stream, data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从指定流反序列化数据。
|
||||
/// </summary>
|
||||
/// <param name="stream">指定流。</param>
|
||||
/// <returns>反序列化的数据。</returns>
|
||||
public T Deserialize(Stream stream)
|
||||
{
|
||||
byte[] header = GetHeader();
|
||||
byte header0 = (byte)stream.ReadByte();
|
||||
byte header1 = (byte)stream.ReadByte();
|
||||
byte header2 = (byte)stream.ReadByte();
|
||||
if (header0 != header[0] || header1 != header[1] || header2 != header[2])
|
||||
{
|
||||
throw new GameFrameworkException(Utility.Text.Format("Header is invalid, need '{0}{1}{2}', current '{3}{4}{5}'.", (char)header[0], (char)header[1], (char)header[2], (char)header0, (char)header1, (char)header2));
|
||||
}
|
||||
|
||||
byte version = (byte)stream.ReadByte();
|
||||
if (!_deserializeCallbacks.TryGetValue(version, out var callback))
|
||||
{
|
||||
throw new GameFrameworkException(Utility.Text.Format("Deserialize callback '{0}' is not exist.", version));
|
||||
}
|
||||
|
||||
return callback(stream);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 尝试从指定流获取指定键的值。
|
||||
/// </summary>
|
||||
/// <param name="stream">指定流。</param>
|
||||
/// <param name="key">指定键。</param>
|
||||
/// <param name="value">指定键的值。</param>
|
||||
/// <returns>是否从指定流获取指定键的值成功。</returns>
|
||||
public bool TryGetValue(Stream stream, string key, out object value)
|
||||
{
|
||||
value = null;
|
||||
byte[] header = GetHeader();
|
||||
byte header0 = (byte)stream.ReadByte();
|
||||
byte header1 = (byte)stream.ReadByte();
|
||||
byte header2 = (byte)stream.ReadByte();
|
||||
if (header0 != header[0] || header1 != header[1] || header2 != header[2])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
byte version = (byte)stream.ReadByte();
|
||||
if (!_tryGetValueCallbacks.TryGetValue(version, out var callback))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return callback(stream, key, out value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取数据头标识。
|
||||
/// </summary>
|
||||
/// <returns>数据头标识。</returns>
|
||||
protected abstract byte[] GetHeader();
|
||||
}
|
||||
}
|
||||
@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2c8469a7db4474e1da10e383bc09e77f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -39,7 +39,6 @@ namespace AlicizaX
|
||||
private static readonly Dictionary<Type, MemoryPoolHandle> s_Handles
|
||||
= new Dictionary<Type, MemoryPoolHandle>(64);
|
||||
|
||||
// Tick 回调用数组缓存,避免每帧遍历 Dictionary
|
||||
private static Action<int>[] s_TickArray = Array.Empty<Action<int>>();
|
||||
private static int s_TickCount;
|
||||
private static bool s_TickArrayDirty;
|
||||
|
||||
@ -1,181 +1,28 @@
|
||||
using System;
|
||||
using System;
|
||||
|
||||
namespace AlicizaX.ObjectPool
|
||||
{
|
||||
public interface IObjectPool
|
||||
public interface IObjectPool<T> where T : ObjectBase
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 对象池接口。
|
||||
/// </summary>
|
||||
/// <typeparam name="T">对象类型。</typeparam>
|
||||
public interface IObjectPool<T> : IObjectPool where T : ObjectBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取对象池名称。
|
||||
/// </summary>
|
||||
string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取对象池完整名称。
|
||||
/// </summary>
|
||||
string FullName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取对象池对象类型。
|
||||
/// </summary>
|
||||
Type ObjectType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取对象池中对象的数量。
|
||||
/// </summary>
|
||||
int Count { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取对象池中能被释放的对象的数量。
|
||||
/// </summary>
|
||||
int CanReleaseCount { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取是否允许对象被多次获取。
|
||||
/// </summary>
|
||||
bool AllowMultiSpawn { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置对象池自动释放可释放对象的间隔秒数。
|
||||
/// </summary>
|
||||
float AutoReleaseInterval { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置对象池的容量。
|
||||
/// </summary>
|
||||
int Capacity { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置对象池对象过期秒数。
|
||||
/// </summary>
|
||||
float ExpireTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置对象池的优先级。
|
||||
/// </summary>
|
||||
int Priority { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 创建对象。
|
||||
/// </summary>
|
||||
/// <param name="obj">对象。</param>
|
||||
/// <param name="spawned">对象是否已被获取。</param>
|
||||
void Register(T obj, bool spawned);
|
||||
|
||||
/// <summary>
|
||||
/// 检查对象。
|
||||
/// </summary>
|
||||
/// <returns>要检查的对象是否存在。</returns>
|
||||
bool CanSpawn();
|
||||
|
||||
/// <summary>
|
||||
/// 检查对象。
|
||||
/// </summary>
|
||||
/// <param name="name">对象名称。</param>
|
||||
/// <returns>要检查的对象是否存在。</returns>
|
||||
bool CanSpawn(string name);
|
||||
|
||||
/// <summary>
|
||||
/// 获取对象。
|
||||
/// </summary>
|
||||
/// <returns>要获取的对象。</returns>
|
||||
T Spawn();
|
||||
|
||||
/// <summary>
|
||||
/// 获取对象。
|
||||
/// </summary>
|
||||
/// <param name="name">对象名称。</param>
|
||||
/// <returns>要获取的对象。</returns>
|
||||
T Spawn(string name);
|
||||
|
||||
/// <summary>
|
||||
/// 回收对象。
|
||||
/// </summary>
|
||||
/// <param name="obj">要回收的对象。</param>
|
||||
void Unspawn(T obj);
|
||||
|
||||
/// <summary>
|
||||
/// 回收对象。
|
||||
/// </summary>
|
||||
/// <param name="target">要回收的对象。</param>
|
||||
void Unspawn(object target);
|
||||
|
||||
/// <summary>
|
||||
/// 设置对象是否被加锁。
|
||||
/// </summary>
|
||||
/// <param name="obj">要设置被加锁的对象。</param>
|
||||
/// <param name="locked">是否被加锁。</param>
|
||||
void SetLocked(T obj, bool locked);
|
||||
|
||||
/// <summary>
|
||||
/// 设置对象是否被加锁。
|
||||
/// </summary>
|
||||
/// <param name="target">要设置被加锁的对象。</param>
|
||||
/// <param name="locked">是否被加锁。</param>
|
||||
void SetLocked(object target, bool locked);
|
||||
|
||||
/// <summary>
|
||||
/// 设置对象的优先级。
|
||||
/// </summary>
|
||||
/// <param name="obj">要设置优先级的对象。</param>
|
||||
/// <param name="priority">优先级。</param>
|
||||
void SetPriority(T obj, int priority);
|
||||
|
||||
/// <summary>
|
||||
/// 设置对象的优先级。
|
||||
/// </summary>
|
||||
/// <param name="target">要设置优先级的对象。</param>
|
||||
/// <param name="priority">优先级。</param>
|
||||
void SetPriority(object target, int priority);
|
||||
|
||||
/// <summary>
|
||||
/// 释放对象。
|
||||
/// </summary>
|
||||
/// <param name="obj">要释放的对象。</param>
|
||||
/// <returns>释放对象是否成功。</returns>
|
||||
bool ReleaseObject(T obj);
|
||||
|
||||
/// <summary>
|
||||
/// 释放对象。
|
||||
/// </summary>
|
||||
/// <param name="target">要释放的对象。</param>
|
||||
/// <returns>释放对象是否成功。</returns>
|
||||
bool ReleaseObject(object target);
|
||||
|
||||
/// <summary>
|
||||
/// 释放对象池中的可释放对象。
|
||||
/// </summary>
|
||||
void Release();
|
||||
|
||||
/// <summary>
|
||||
/// 释放对象池中的可释放对象。
|
||||
/// </summary>
|
||||
/// <param name="toReleaseCount">尝试释放对象数量。</param>
|
||||
void Release(int toReleaseCount);
|
||||
|
||||
/// <summary>
|
||||
/// 释放对象池中的可释放对象。
|
||||
/// </summary>
|
||||
/// <param name="releaseObjectFilterCallback">释放对象筛选函数。</param>
|
||||
void Release(ReleaseObjectFilterCallback<T> releaseObjectFilterCallback);
|
||||
|
||||
/// <summary>
|
||||
/// 释放对象池中的可释放对象。
|
||||
/// </summary>
|
||||
/// <param name="toReleaseCount">尝试释放对象数量。</param>
|
||||
/// <param name="releaseObjectFilterCallback">释放对象筛选函数。</param>
|
||||
void Release(int toReleaseCount, ReleaseObjectFilterCallback<T> releaseObjectFilterCallback);
|
||||
|
||||
/// <summary>
|
||||
/// 释放对象池中的所有未使用对象。
|
||||
/// </summary>
|
||||
void ReleaseAllUnused();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using AlicizaX;
|
||||
|
||||
namespace AlicizaX.ObjectPool
|
||||
{
|
||||
@ -8,17 +7,17 @@ namespace AlicizaX.ObjectPool
|
||||
{
|
||||
public readonly string Name;
|
||||
public readonly bool AllowMultiSpawn;
|
||||
public readonly float AutoReleaseInterval;
|
||||
public readonly int Capacity;
|
||||
public readonly float ExpireTime;
|
||||
public readonly float? AutoReleaseInterval;
|
||||
public readonly int? Capacity;
|
||||
public readonly float? ExpireTime;
|
||||
public readonly int Priority;
|
||||
|
||||
public ObjectPoolCreateOptions(
|
||||
string name = "",
|
||||
bool allowMultiSpawn = false,
|
||||
float autoReleaseInterval = float.MaxValue,
|
||||
int capacity = int.MaxValue,
|
||||
float expireTime = float.MaxValue,
|
||||
float? autoReleaseInterval = null,
|
||||
int? capacity = null,
|
||||
float? expireTime = null,
|
||||
int priority = 0)
|
||||
{
|
||||
Name = name ?? string.Empty;
|
||||
@ -39,37 +38,32 @@ namespace AlicizaX.ObjectPool
|
||||
=> new ObjectPoolCreateOptions(name: name, allowMultiSpawn: true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 对象池管理器。
|
||||
/// </summary>
|
||||
|
||||
public interface IObjectPoolService : IService
|
||||
{
|
||||
int Count { get; }
|
||||
|
||||
bool HasObjectPool<T>() where T : ObjectBase;
|
||||
bool HasObjectPool(Type objectType);
|
||||
bool HasObjectPool<T>(string name) where T : ObjectBase;
|
||||
bool HasObjectPool(Type objectType);
|
||||
bool HasObjectPool(Type objectType, string name);
|
||||
bool HasObjectPool(Predicate<ObjectPoolBase> condition);
|
||||
|
||||
IObjectPool<T> GetObjectPool<T>() where T : ObjectBase;
|
||||
ObjectPoolBase GetObjectPool(Type objectType);
|
||||
IObjectPool<T> GetObjectPool<T>(string name) where T : ObjectBase;
|
||||
ObjectPoolBase GetObjectPool(Type objectType);
|
||||
ObjectPoolBase GetObjectPool(Type objectType, string name);
|
||||
ObjectPoolBase GetObjectPool(Predicate<ObjectPoolBase> condition);
|
||||
ObjectPoolBase[] GetObjectPools(Predicate<ObjectPoolBase> condition);
|
||||
void GetObjectPools(Predicate<ObjectPoolBase> condition, List<ObjectPoolBase> results);
|
||||
|
||||
ObjectPoolBase[] GetAllObjectPools();
|
||||
void GetAllObjectPools(List<ObjectPoolBase> results);
|
||||
ObjectPoolBase[] GetAllObjectPools(bool sort);
|
||||
void GetAllObjectPools(List<ObjectPoolBase> results);
|
||||
void GetAllObjectPools(bool sort, List<ObjectPoolBase> results);
|
||||
|
||||
IObjectPool<T> CreatePool<T>(ObjectPoolCreateOptions options = default) where T : ObjectBase;
|
||||
ObjectPoolBase CreatePool(Type objectType, ObjectPoolCreateOptions options = default);
|
||||
|
||||
bool DestroyObjectPool<T>() where T : ObjectBase;
|
||||
bool DestroyObjectPool(Type objectType);
|
||||
bool DestroyObjectPool<T>(string name) where T : ObjectBase;
|
||||
bool DestroyObjectPool(Type objectType);
|
||||
bool DestroyObjectPool(Type objectType, string name);
|
||||
bool DestroyObjectPool<T>(IObjectPool<T> objectPool) where T : ObjectBase;
|
||||
bool DestroyObjectPool(ObjectPoolBase objectPool);
|
||||
|
||||
170
Runtime/ABase/ObjectPool/IntOpenHashMap.cs
Normal file
170
Runtime/ABase/ObjectPool/IntOpenHashMap.cs
Normal file
@ -0,0 +1,170 @@
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace AlicizaX.ObjectPool
|
||||
{
|
||||
|
||||
internal struct IntOpenHashMap
|
||||
{
|
||||
private int[] m_Buckets;
|
||||
private int[] m_Keys;
|
||||
private int[] m_Values;
|
||||
private int[] m_Next;
|
||||
private int m_Count;
|
||||
private int m_FreeList;
|
||||
private int m_Mask;
|
||||
private int m_AllocCount;
|
||||
|
||||
private const int MinCapacity = 8;
|
||||
|
||||
public int Count => m_Count;
|
||||
|
||||
public IntOpenHashMap(int capacity)
|
||||
{
|
||||
int cap = NextPowerOf2(Math.Max(capacity, MinCapacity));
|
||||
m_Mask = cap - 1;
|
||||
m_Buckets = new int[cap];
|
||||
m_Keys = new int[cap];
|
||||
m_Values = new int[cap];
|
||||
m_Next = new int[cap];
|
||||
m_Count = 0;
|
||||
m_FreeList = 0;
|
||||
m_AllocCount = 0;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool TryGetValue(int key, out int value)
|
||||
{
|
||||
if (m_Buckets == null) { value = -1; return false; }
|
||||
int i = m_Buckets[(key & 0x7FFFFFFF) & m_Mask];
|
||||
while (i > 0)
|
||||
{
|
||||
int idx = i - 1;
|
||||
if (m_Keys[idx] == key) { value = m_Values[idx]; return true; }
|
||||
i = m_Next[idx];
|
||||
}
|
||||
value = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void AddOrUpdate(int key, int value)
|
||||
{
|
||||
if (m_Count >= ((m_Mask + 1) * 3 >> 2))
|
||||
Grow();
|
||||
|
||||
int bucket = (key & 0x7FFFFFFF) & m_Mask;
|
||||
int i = m_Buckets[bucket];
|
||||
while (i > 0)
|
||||
{
|
||||
int ei = i - 1;
|
||||
if (m_Keys[ei] == key) { m_Values[ei] = value; return; }
|
||||
i = m_Next[ei];
|
||||
}
|
||||
|
||||
int idx;
|
||||
if (m_FreeList > 0)
|
||||
{
|
||||
idx = m_FreeList - 1;
|
||||
m_FreeList = m_Next[idx];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_AllocCount > m_Mask) { Grow(); bucket = (key & 0x7FFFFFFF) & m_Mask; }
|
||||
idx = m_AllocCount++;
|
||||
}
|
||||
|
||||
m_Keys[idx] = key;
|
||||
m_Values[idx] = value;
|
||||
m_Next[idx] = m_Buckets[bucket];
|
||||
m_Buckets[bucket] = idx + 1;
|
||||
m_Count++;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool Remove(int key)
|
||||
{
|
||||
if (m_Buckets == null) return false;
|
||||
int bucket = (key & 0x7FFFFFFF) & m_Mask;
|
||||
int prev = 0;
|
||||
int i = m_Buckets[bucket];
|
||||
while (i > 0)
|
||||
{
|
||||
int idx = i - 1;
|
||||
if (m_Keys[idx] == key)
|
||||
{
|
||||
if (prev == 0) m_Buckets[bucket] = m_Next[idx];
|
||||
else m_Next[prev - 1] = m_Next[idx];
|
||||
m_Keys[idx] = 0;
|
||||
m_Values[idx] = -1;
|
||||
m_Next[idx] = m_FreeList;
|
||||
m_FreeList = idx + 1;
|
||||
m_Count--;
|
||||
return true;
|
||||
}
|
||||
prev = i;
|
||||
i = m_Next[idx];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
if (m_Buckets == null) return;
|
||||
int cap = m_Mask + 1;
|
||||
Array.Clear(m_Buckets, 0, cap);
|
||||
Array.Clear(m_Keys, 0, cap);
|
||||
Array.Clear(m_Values, 0, cap);
|
||||
Array.Clear(m_Next, 0, cap);
|
||||
m_Count = 0;
|
||||
m_FreeList = 0;
|
||||
m_AllocCount = 0;
|
||||
}
|
||||
|
||||
private void Grow()
|
||||
{
|
||||
int newCap = (m_Mask + 1) << 1;
|
||||
if (newCap < MinCapacity) newCap = MinCapacity;
|
||||
int newMask = newCap - 1;
|
||||
var newBuckets = new int[newCap];
|
||||
var newKeys = new int[newCap];
|
||||
var newValues = new int[newCap];
|
||||
var newNext = new int[newCap];
|
||||
|
||||
int newAlloc = 0;
|
||||
int oldCap = m_Mask + 1;
|
||||
for (int b = 0; b < oldCap; b++)
|
||||
{
|
||||
int i = m_Buckets[b];
|
||||
while (i > 0)
|
||||
{
|
||||
int old = i - 1;
|
||||
int ni = newAlloc++;
|
||||
newKeys[ni] = m_Keys[old];
|
||||
newValues[ni] = m_Values[old];
|
||||
int nb = (newKeys[ni] & 0x7FFFFFFF) & newMask;
|
||||
newNext[ni] = newBuckets[nb];
|
||||
newBuckets[nb] = ni + 1;
|
||||
i = m_Next[old];
|
||||
}
|
||||
}
|
||||
|
||||
m_Buckets = newBuckets;
|
||||
m_Keys = newKeys;
|
||||
m_Values = newValues;
|
||||
m_Next = newNext;
|
||||
m_Mask = newMask;
|
||||
m_AllocCount = newAlloc;
|
||||
m_FreeList = 0;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static int NextPowerOf2(int v)
|
||||
{
|
||||
v--;
|
||||
v |= v >> 1; v |= v >> 2; v |= v >> 4;
|
||||
v |= v >> 8; v |= v >> 16;
|
||||
return v + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ce20200ce38864c44b02e0c1ebc7fc3a
|
||||
guid: 6e20a3f64bc47ae4dbf407342897a015
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@ -1,175 +1,57 @@
|
||||
using System;
|
||||
using AlicizaX;
|
||||
|
||||
namespace AlicizaX.ObjectPool
|
||||
{
|
||||
/// <summary>
|
||||
/// 对象基类。
|
||||
/// </summary>
|
||||
public abstract class ObjectBase : IMemory
|
||||
{
|
||||
private string m_Name;
|
||||
private object m_Target;
|
||||
private bool m_Locked;
|
||||
private int m_Priority;
|
||||
private DateTime m_LastUseTime;
|
||||
private float m_LastUseTime;
|
||||
|
||||
/// <summary>
|
||||
/// 初始化对象基类的新实例。
|
||||
/// </summary>
|
||||
public ObjectBase()
|
||||
{
|
||||
m_Name = null;
|
||||
m_Target = null;
|
||||
m_Locked = false;
|
||||
m_Priority = 0;
|
||||
m_LastUseTime = default(DateTime);
|
||||
}
|
||||
public string Name => m_Name;
|
||||
public object Target => m_Target;
|
||||
|
||||
/// <summary>
|
||||
/// 获取对象名称。
|
||||
/// </summary>
|
||||
public virtual string Name
|
||||
{
|
||||
get { return m_Name; }
|
||||
protected set { m_Name = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取对象。
|
||||
/// </summary>
|
||||
public object Target
|
||||
{
|
||||
get { return m_Target; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置对象是否被加锁。
|
||||
/// </summary>
|
||||
public bool Locked
|
||||
{
|
||||
get { return m_Locked; }
|
||||
set { m_Locked = value; }
|
||||
get => m_Locked;
|
||||
set => m_Locked = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置对象的优先级。
|
||||
/// </summary>
|
||||
public int Priority
|
||||
public float LastUseTime
|
||||
{
|
||||
get { return m_Priority; }
|
||||
set { m_Priority = value; }
|
||||
get => m_LastUseTime;
|
||||
internal set => m_LastUseTime = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取自定义释放检查标记。
|
||||
/// </summary>
|
||||
public virtual bool CustomCanReleaseFlag
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
public virtual bool CustomCanReleaseFlag => true;
|
||||
|
||||
/// <summary>
|
||||
/// 获取对象上次使用时间。
|
||||
/// </summary>
|
||||
public DateTime LastUseTime
|
||||
{
|
||||
get { return m_LastUseTime; }
|
||||
internal set { m_LastUseTime = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 初始化对象基类。
|
||||
/// </summary>
|
||||
/// <param name="target">对象。</param>
|
||||
protected void Initialize(object target)
|
||||
{
|
||||
Initialize(null, target, false, 0);
|
||||
Initialize(string.Empty, target, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 初始化对象基类。
|
||||
/// </summary>
|
||||
/// <param name="name">对象名称。</param>
|
||||
/// <param name="target">对象。</param>
|
||||
protected void Initialize(string name, object target)
|
||||
{
|
||||
Initialize(name, target, false, 0);
|
||||
Initialize(name, target, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 初始化对象基类。
|
||||
/// </summary>
|
||||
/// <param name="name">对象名称。</param>
|
||||
/// <param name="target">对象。</param>
|
||||
/// <param name="locked">对象是否被加锁。</param>
|
||||
protected void Initialize(string name, object target, bool locked)
|
||||
{
|
||||
Initialize(name, target, locked, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 初始化对象基类。
|
||||
/// </summary>
|
||||
/// <param name="name">对象名称。</param>
|
||||
/// <param name="target">对象。</param>
|
||||
/// <param name="priority">对象的优先级。</param>
|
||||
protected void Initialize(string name, object target, int priority)
|
||||
{
|
||||
Initialize(name, target, false, priority);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 初始化对象基类。
|
||||
/// </summary>
|
||||
/// <param name="name">对象名称。</param>
|
||||
/// <param name="target">对象。</param>
|
||||
/// <param name="locked">对象是否被加锁。</param>
|
||||
/// <param name="priority">对象的优先级。</param>
|
||||
protected void Initialize(string name, object target, bool locked, int priority)
|
||||
{
|
||||
if (target == null)
|
||||
{
|
||||
throw new GameFrameworkException(Utility.Text.Format("Target '{0}' is invalid.", name));
|
||||
}
|
||||
|
||||
m_Name = name ?? string.Empty;
|
||||
m_Target = target;
|
||||
m_Locked = locked;
|
||||
m_Priority = priority;
|
||||
m_LastUseTime = DateTime.UtcNow;
|
||||
m_LastUseTime = 0f;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清理对象基类。
|
||||
/// </summary>
|
||||
protected internal virtual void OnSpawn() { }
|
||||
protected internal virtual void OnUnspawn() { }
|
||||
protected internal abstract void Release(bool isShutdown);
|
||||
|
||||
public virtual void Clear()
|
||||
{
|
||||
m_Name = null;
|
||||
m_Target = null;
|
||||
m_Locked = false;
|
||||
m_Priority = 0;
|
||||
m_LastUseTime = default(DateTime);
|
||||
m_LastUseTime = 0f;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取对象时的事件。
|
||||
/// </summary>
|
||||
protected internal virtual void OnSpawn()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 回收对象时的事件。
|
||||
/// </summary>
|
||||
protected internal virtual void OnUnspawn()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 释放对象。
|
||||
/// </summary>
|
||||
/// <param name="isShutdown">是否是关闭对象池时触发。</param>
|
||||
protected internal abstract void Release(bool isShutdown);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,115 +1,27 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace AlicizaX.ObjectPool
|
||||
{
|
||||
/// <summary>
|
||||
/// 对象信息。
|
||||
/// </summary>
|
||||
|
||||
[StructLayout(LayoutKind.Auto)]
|
||||
public struct ObjectInfo
|
||||
public readonly struct ObjectInfo
|
||||
{
|
||||
private readonly string m_Name;
|
||||
private readonly bool m_Locked;
|
||||
private readonly bool m_CustomCanReleaseFlag;
|
||||
private readonly int m_Priority;
|
||||
private readonly DateTime m_LastUseTime;
|
||||
private readonly int m_SpawnCount;
|
||||
public readonly string Name;
|
||||
public readonly bool Locked;
|
||||
public readonly bool CustomCanReleaseFlag;
|
||||
public readonly float LastUseTime;
|
||||
public readonly int SpawnCount;
|
||||
|
||||
/// <summary>
|
||||
/// 初始化对象信息的新实例。
|
||||
/// </summary>
|
||||
/// <param name="name">对象名称。</param>
|
||||
/// <param name="locked">对象是否被加锁。</param>
|
||||
/// <param name="customCanReleaseFlag">对象自定义释放检查标记。</param>
|
||||
/// <param name="priority">对象的优先级。</param>
|
||||
/// <param name="lastUseTime">对象上次使用时间。</param>
|
||||
/// <param name="spawnCount">对象的获取计数。</param>
|
||||
public ObjectInfo(string name, bool locked, bool customCanReleaseFlag, int priority, DateTime lastUseTime, int spawnCount)
|
||||
public ObjectInfo(string name, bool locked, bool customCanReleaseFlag,
|
||||
float lastUseTime, int spawnCount)
|
||||
{
|
||||
m_Name = name;
|
||||
m_Locked = locked;
|
||||
m_CustomCanReleaseFlag = customCanReleaseFlag;
|
||||
m_Priority = priority;
|
||||
m_LastUseTime = lastUseTime;
|
||||
m_SpawnCount = spawnCount;
|
||||
Name = name;
|
||||
Locked = locked;
|
||||
CustomCanReleaseFlag = customCanReleaseFlag;
|
||||
LastUseTime = lastUseTime;
|
||||
SpawnCount = spawnCount;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取对象名称。
|
||||
/// </summary>
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Name;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取对象是否被加锁。
|
||||
/// </summary>
|
||||
public bool Locked
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Locked;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取对象自定义释放检查标记。
|
||||
/// </summary>
|
||||
public bool CustomCanReleaseFlag
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_CustomCanReleaseFlag;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取对象的优先级。
|
||||
/// </summary>
|
||||
public int Priority
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Priority;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取对象上次使用时间。
|
||||
/// </summary>
|
||||
public DateTime LastUseTime
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_LastUseTime;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取对象是否正在使用。
|
||||
/// </summary>
|
||||
public bool IsInUse
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_SpawnCount > 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取对象的获取计数。
|
||||
/// </summary>
|
||||
public int SpawnCount
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_SpawnCount;
|
||||
}
|
||||
}
|
||||
public bool IsInUse => SpawnCount > 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,149 +1,53 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using AlicizaX;
|
||||
|
||||
namespace AlicizaX.ObjectPool
|
||||
{
|
||||
/// <summary>
|
||||
/// 对象池基类。
|
||||
/// </summary>
|
||||
|
||||
public abstract class ObjectPoolBase
|
||||
{
|
||||
private readonly string m_Name;
|
||||
|
||||
/// <summary>
|
||||
/// 初始化对象池基类的新实例。
|
||||
/// </summary>
|
||||
public ObjectPoolBase()
|
||||
: this(null)
|
||||
{
|
||||
}
|
||||
public ObjectPoolBase() : this(null) { }
|
||||
|
||||
/// <summary>
|
||||
/// 初始化对象池基类的新实例。
|
||||
/// </summary>
|
||||
/// <param name="name">对象池名称。</param>
|
||||
public ObjectPoolBase(string name)
|
||||
{
|
||||
m_Name = name ?? string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取对象池名称。
|
||||
/// </summary>
|
||||
public string Name
|
||||
public string Name => m_Name;
|
||||
|
||||
public string FullName => new TypeNamePair(ObjectType, m_Name).ToString();
|
||||
|
||||
public abstract Type ObjectType { get; }
|
||||
public abstract int Count { get; }
|
||||
public abstract bool AllowMultiSpawn { get; }
|
||||
|
||||
public abstract float AutoReleaseInterval { get; set; }
|
||||
public abstract int Capacity { get; set; }
|
||||
public abstract float ExpireTime { get; set; }
|
||||
public abstract int Priority { get; set; }
|
||||
|
||||
|
||||
public virtual int ReleasePerFrameBudget
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Name;
|
||||
}
|
||||
get => 8;
|
||||
set { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取对象池完整名称。
|
||||
/// </summary>
|
||||
public string FullName
|
||||
{
|
||||
get
|
||||
{
|
||||
return new TypeNamePair(ObjectType, m_Name).ToString();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取对象池对象类型。
|
||||
/// </summary>
|
||||
public abstract Type ObjectType
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取对象池中对象的数量。
|
||||
/// </summary>
|
||||
public abstract int Count
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取对象池中能被释放的对象的数量。
|
||||
/// </summary>
|
||||
public abstract int CanReleaseCount
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取是否允许对象被多次获取。
|
||||
/// </summary>
|
||||
public abstract bool AllowMultiSpawn
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置对象池自动释放可释放对象的间隔秒数。
|
||||
/// </summary>
|
||||
public abstract float AutoReleaseInterval
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置对象池的容量。
|
||||
/// </summary>
|
||||
public abstract int Capacity
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置对象池对象过期秒数。
|
||||
/// </summary>
|
||||
public abstract float ExpireTime
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置对象池的优先级。
|
||||
/// </summary>
|
||||
public abstract int Priority
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 释放对象池中的可释放对象。
|
||||
/// </summary>
|
||||
public abstract void Release();
|
||||
|
||||
/// <summary>
|
||||
/// 释放对象池中的可释放对象。
|
||||
/// </summary>
|
||||
/// <param name="toReleaseCount">尝试释放对象数量。</param>
|
||||
public abstract void Release(int toReleaseCount);
|
||||
|
||||
/// <summary>
|
||||
/// 释放对象池中的所有未使用对象。
|
||||
/// </summary>
|
||||
public abstract void ReleaseAllUnused();
|
||||
|
||||
/// <summary>
|
||||
/// 获取所有对象信息。
|
||||
/// </summary>
|
||||
/// <returns>所有对象信息。</returns>
|
||||
public abstract ObjectInfo[] GetAllObjectInfos();
|
||||
|
||||
public abstract void GetAllObjectInfos(List<ObjectInfo> results);
|
||||
|
||||
internal abstract void Update(float elapseSeconds, float realElapseSeconds);
|
||||
|
||||
internal abstract void Shutdown();
|
||||
|
||||
internal virtual void OnLowMemory()
|
||||
{
|
||||
ReleaseAllUnused();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,40 +3,34 @@ using UnityEngine;
|
||||
|
||||
namespace AlicizaX
|
||||
{
|
||||
/// <summary>
|
||||
/// 对象池组件。
|
||||
/// </summary>
|
||||
|
||||
public sealed class ObjectPoolComponent : MonoBehaviour
|
||||
{
|
||||
private IObjectPoolService _mObjectPoolService = null;
|
||||
private IObjectPoolService _mObjectPoolService;
|
||||
|
||||
/// <summary>
|
||||
/// 获取对象池数量。
|
||||
/// </summary>
|
||||
public int Count
|
||||
{
|
||||
get { return _mObjectPoolService.Count; }
|
||||
}
|
||||
public int Count => _mObjectPoolService.Count;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_mObjectPoolService = AppServices.RegisterApp(new ObjectPoolService());
|
||||
Application.lowMemory += OnLowMemory;
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
Application.lowMemory -= OnLowMemory;
|
||||
_mObjectPoolService = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取所有对象池。
|
||||
/// </summary>
|
||||
/// <param name="sort">是否根据对象池的优先级排序。</param>
|
||||
/// <returns>所有对象池。</returns>
|
||||
private void OnLowMemory()
|
||||
{
|
||||
if (_mObjectPoolService is ObjectPoolService svc)
|
||||
svc.OnLowMemory();
|
||||
}
|
||||
|
||||
public ObjectPoolBase[] GetAllObjectPools(bool sort)
|
||||
{
|
||||
return _mObjectPoolService.GetAllObjectPools(sort);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,180 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using AlicizaX;
|
||||
|
||||
namespace AlicizaX.ObjectPool
|
||||
{
|
||||
internal sealed partial class ObjectPoolService : IObjectPoolService
|
||||
{
|
||||
/// <summary>
|
||||
/// 内部对象。
|
||||
/// </summary>
|
||||
/// <typeparam name="T">对象类型。</typeparam>
|
||||
private sealed class Object<T> : IMemory where T : ObjectBase
|
||||
{
|
||||
private string m_Name;
|
||||
private T m_Object;
|
||||
private int m_SpawnCount;
|
||||
private LinkedListNode<Object<T>> m_NameNode;
|
||||
|
||||
/// <summary>
|
||||
/// 初始化内部对象的新实例。
|
||||
/// </summary>
|
||||
public Object()
|
||||
{
|
||||
m_Name = null;
|
||||
m_Object = null;
|
||||
m_SpawnCount = 0;
|
||||
m_NameNode = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取对象名称。
|
||||
/// </summary>
|
||||
public string Name
|
||||
{
|
||||
get { return m_Name; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取对象是否被加锁。
|
||||
/// </summary>
|
||||
public bool Locked
|
||||
{
|
||||
get { return m_Object.Locked; }
|
||||
internal set { m_Object.Locked = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取对象的优先级。
|
||||
/// </summary>
|
||||
public int Priority
|
||||
{
|
||||
get { return m_Object.Priority; }
|
||||
internal set { m_Object.Priority = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取自定义释放检查标记。
|
||||
/// </summary>
|
||||
public bool CustomCanReleaseFlag
|
||||
{
|
||||
get { return m_Object.CustomCanReleaseFlag; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取对象上次使用时间。
|
||||
/// </summary>
|
||||
public DateTime LastUseTime
|
||||
{
|
||||
get { return m_Object.LastUseTime; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取对象是否正在使用。
|
||||
/// </summary>
|
||||
public bool IsInUse
|
||||
{
|
||||
get { return m_SpawnCount > 0; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取对象的获取计数。
|
||||
/// </summary>
|
||||
public int SpawnCount
|
||||
{
|
||||
get { return m_SpawnCount; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置对象在名字桶中的链表结点。
|
||||
/// </summary>
|
||||
public LinkedListNode<Object<T>> NameNode
|
||||
{
|
||||
get { return m_NameNode; }
|
||||
internal set { m_NameNode = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建内部对象。
|
||||
/// </summary>
|
||||
/// <param name="obj">对象。</param>
|
||||
/// <param name="spawned">对象是否已被获取。</param>
|
||||
/// <returns>创建的内部对象。</returns>
|
||||
public static Object<T> Create(T obj, bool spawned)
|
||||
{
|
||||
if (obj == null)
|
||||
{
|
||||
throw new GameFrameworkException("Object is invalid.");
|
||||
}
|
||||
|
||||
Object<T> internalObject = MemoryPool.Acquire<Object<T>>();
|
||||
internalObject.m_Name = obj.Name;
|
||||
internalObject.m_Object = obj;
|
||||
internalObject.m_SpawnCount = spawned ? 1 : 0;
|
||||
if (spawned)
|
||||
{
|
||||
obj.OnSpawn();
|
||||
}
|
||||
|
||||
return internalObject;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清理内部对象。
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
m_Name = null;
|
||||
m_Object = null;
|
||||
m_SpawnCount = 0;
|
||||
m_NameNode = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查看对象。
|
||||
/// </summary>
|
||||
/// <returns>对象。</returns>
|
||||
public T Peek()
|
||||
{
|
||||
return m_Object;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取对象。
|
||||
/// </summary>
|
||||
/// <returns>对象。</returns>
|
||||
public T Spawn()
|
||||
{
|
||||
m_SpawnCount++;
|
||||
m_Object.LastUseTime = DateTime.UtcNow;
|
||||
m_Object.OnSpawn();
|
||||
return m_Object;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 回收对象。
|
||||
/// </summary>
|
||||
public void Unspawn()
|
||||
{
|
||||
m_Object.LastUseTime = DateTime.UtcNow;
|
||||
m_Object.OnUnspawn();
|
||||
m_SpawnCount--;
|
||||
if (m_SpawnCount < 0)
|
||||
{
|
||||
throw new GameFrameworkException(Utility.Text.Format("Object '{0}' spawn count is less than 0.", Name));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 释放对象。
|
||||
/// </summary>
|
||||
/// <param name="isShutdown">是否是关闭对象池时触发。</param>
|
||||
public void Release(bool isShutdown)
|
||||
{
|
||||
m_Object.Release(isShutdown);
|
||||
MemoryPool.Release(m_Object);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 35ccf480f8b7a42a4ba523c51d58e544
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,15 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace AlicizaX.ObjectPool
|
||||
{
|
||||
/// <summary>
|
||||
/// 释放对象筛选函数。
|
||||
/// </summary>
|
||||
/// <typeparam name="T">对象类型。</typeparam>
|
||||
/// <param name="candidateObjects">要筛选的对象集合。</param>
|
||||
/// <param name="toReleaseCount">需要释放的对象数量。</param>
|
||||
/// <param name="expireTime">对象过期参考时间。</param>
|
||||
/// <returns>经筛选需要释放的对象集合。</returns>
|
||||
public delegate List<T> ReleaseObjectFilterCallback<T>(List<T> candidateObjects, int toReleaseCount, DateTime expireTime) where T : ObjectBase;
|
||||
}
|
||||
@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7109de176e3874b1d863ca0d2cdba894
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -36,7 +36,6 @@ namespace AlicizaX.Debugger.Runtime
|
||||
card.Add(CreateRow("Auto Release Interval", objectPool.AutoReleaseInterval.ToString()));
|
||||
card.Add(CreateRow("Capacity", objectPool.Capacity.ToString()));
|
||||
card.Add(CreateRow("Used Count", objectPool.Count.ToString()));
|
||||
card.Add(CreateRow("Can Release Count", objectPool.CanReleaseCount.ToString()));
|
||||
card.Add(CreateRow("Expire Time", objectPool.ExpireTime.ToString()));
|
||||
card.Add(CreateRow("Priority", objectPool.Priority.ToString()));
|
||||
|
||||
@ -52,13 +51,12 @@ namespace AlicizaX.Debugger.Runtime
|
||||
ObjectInfo info = objectInfos[j];
|
||||
string title = string.IsNullOrEmpty(info.Name) ? "<None>" : info.Name;
|
||||
string content = Utility.Text.Format(
|
||||
"Locked {0} | {1} {2} | Flag {3} | Priority {4} | Last Use {5}",
|
||||
"Locked {0} | {1} {2} | Flag {3} | Last Use {4}",
|
||||
info.Locked,
|
||||
objectPool.AllowMultiSpawn ? "Count" : "InUse",
|
||||
objectPool.AllowMultiSpawn ? info.SpawnCount.ToString() : info.IsInUse.ToString(),
|
||||
info.CustomCanReleaseFlag,
|
||||
info.Priority,
|
||||
info.LastUseTime.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss"));
|
||||
Utility.Text.Format("{0:F1}s ago", Time.realtimeSinceStartup - info.LastUseTime));
|
||||
card.Add(CreateRow(title, content));
|
||||
}
|
||||
}
|
||||
|
||||
@ -15,12 +15,7 @@ namespace AlicizaX.Resource.Runtime
|
||||
|
||||
protected internal override void Release(bool isShutdown)
|
||||
{
|
||||
if (Target == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AppServices.Require<IResourceService>().UnloadAsset(Target);
|
||||
// Asset handle cleanup is owned by ResourceExtComponent/ResourceService.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -204,9 +204,10 @@ namespace AlicizaX.Resource.Runtime
|
||||
_trackedAssetNodes.Remove(trackedObject);
|
||||
}
|
||||
|
||||
if (releaseAsset && node.Value.AssetTarget != null && _assetItemPool != null)
|
||||
if (releaseAsset && node.Value.AssetTarget != null)
|
||||
{
|
||||
_assetItemPool.Unspawn(node.Value.AssetTarget);
|
||||
_resourceService?.UnloadAsset(node.Value.AssetTarget);
|
||||
_assetItemPool?.Unspawn(node.Value.AssetTarget);
|
||||
}
|
||||
|
||||
if (node.Value.AssetObject != null)
|
||||
|
||||
@ -14,7 +14,6 @@ namespace AlicizaX.Resource.Runtime
|
||||
private sealed class AssetObject : ObjectBase
|
||||
{
|
||||
private AssetHandle m_AssetHandle;
|
||||
private IResourceService _resourceService;
|
||||
|
||||
|
||||
public AssetObject()
|
||||
@ -22,22 +21,16 @@ namespace AlicizaX.Resource.Runtime
|
||||
m_AssetHandle = null;
|
||||
}
|
||||
|
||||
public static AssetObject Create(string name, object target, object assetHandle, IResourceService resourceService)
|
||||
public static AssetObject Create(string name, object target, object assetHandle)
|
||||
{
|
||||
if (assetHandle == null)
|
||||
{
|
||||
throw new GameFrameworkException("Resource is invalid.");
|
||||
}
|
||||
|
||||
if (resourceService == null)
|
||||
{
|
||||
throw new GameFrameworkException("Resource Manager is invalid.");
|
||||
}
|
||||
|
||||
AssetObject assetObject = MemoryPool.Acquire<AssetObject>();
|
||||
assetObject.Initialize(name, target);
|
||||
assetObject.m_AssetHandle = (AssetHandle)assetHandle;
|
||||
assetObject._resourceService = resourceService;
|
||||
return assetObject;
|
||||
}
|
||||
|
||||
@ -61,7 +54,6 @@ namespace AlicizaX.Resource.Runtime
|
||||
{
|
||||
handle.Dispose();
|
||||
}
|
||||
handle = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -601,7 +601,7 @@ namespace AlicizaX.Resource.Runtime
|
||||
|
||||
T ret = handle.AssetObject as T;
|
||||
|
||||
assetObject = AssetObject.Create(assetObjectKey, handle.AssetObject, handle, this);
|
||||
assetObject = AssetObject.Create(assetObjectKey, handle.AssetObject, handle);
|
||||
_assetPool.Register(assetObject, true);
|
||||
|
||||
return ret;
|
||||
@ -631,7 +631,7 @@ namespace AlicizaX.Resource.Runtime
|
||||
|
||||
GameObject gameObject = AssetsReference.Instantiate(handle.AssetObject as GameObject, parent, this).gameObject;
|
||||
|
||||
assetObject = AssetObject.Create(assetObjectKey, handle.AssetObject, handle, this);
|
||||
assetObject = AssetObject.Create(assetObjectKey, handle.AssetObject, handle);
|
||||
_assetPool.Register(assetObject, true);
|
||||
|
||||
return gameObject;
|
||||
@ -951,7 +951,7 @@ namespace AlicizaX.Resource.Runtime
|
||||
throw new GameFrameworkException(Utility.Text.Format("Can not load asset '{0}'.", location));
|
||||
}
|
||||
|
||||
var assetObject = AssetObject.Create(assetObjectKey, handle.AssetObject, handle, this);
|
||||
var assetObject = AssetObject.Create(assetObjectKey, handle.AssetObject, handle);
|
||||
_assetPool.Register(assetObject, true);
|
||||
CompleteLoading(assetObjectKey);
|
||||
return handle.AssetObject as UnityEngine.Object;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user