Compare commits
3 Commits
b6d2f38e72
...
bf81df9581
| Author | SHA1 | Date | |
|---|---|---|---|
| bf81df9581 | |||
| 6d72129bae | |||
| 1a28eb62a8 |
8
Convention/[Architecture].meta
Normal file
8
Convention/[Architecture].meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aedf6f9892e6a9545a8e4bfce4d03063
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
114
Convention/[Architecture]/Architecture.cs
Normal file
114
Convention/[Architecture]/Architecture.cs
Normal file
@@ -0,0 +1,114 @@
|
||||
using Convention.Experimental.PublicType;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Convention.Experimental
|
||||
{
|
||||
public static class Architecture
|
||||
{
|
||||
private static readonly LinkedCacheList<GameModule> s_GameFrameworkModules = new();
|
||||
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD><EFBFBD><see cref="GameModule"/>
|
||||
/// </summary>
|
||||
/// <param name="moduleType">Ҫ<><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><see cref="GameModule"/><3E><><EFBFBD><EFBFBD></param>
|
||||
/// <returns>Ҫ<><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><see cref="GameModule"/></returns>
|
||||
private static GameModule CreateModule(Type moduleType, int stackLayer = 0)
|
||||
{
|
||||
if (stackLayer >= 100)
|
||||
{
|
||||
throw new GameException($"Create module '{moduleType.FullName}' failed, recursion too deep, there may be a circular dependency.");
|
||||
}
|
||||
|
||||
GameModule module = (GameModule)Activator.CreateInstance(moduleType);
|
||||
if (module == null)
|
||||
{
|
||||
throw new GameException($"Can not create module '{moduleType.FullName}'");
|
||||
}
|
||||
|
||||
// <20>ݹ鴴<DDB9><E9B4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD><C4A3>
|
||||
foreach (var dependenceType in module.Dependences())
|
||||
_ = GetModule(dependenceType, stackLayer + 1);
|
||||
|
||||
LinkedListNode<GameModule> current = s_GameFrameworkModules.First;
|
||||
while (current != null)
|
||||
{
|
||||
if (module.Priority > current.Value.Priority)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
current = current.Next;
|
||||
}
|
||||
|
||||
if (current != null)
|
||||
{
|
||||
s_GameFrameworkModules.AddBefore(current, module);
|
||||
}
|
||||
else
|
||||
{
|
||||
s_GameFrameworkModules.AddLast(module);
|
||||
}
|
||||
|
||||
return module;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <20><>ȡ<see cref="GameModule"/>
|
||||
/// </summary>
|
||||
/// <param name="moduleType">Ҫ<><D2AA>ȡ<EFBFBD><C8A1><see cref="GameModule"/></param>
|
||||
/// <returns>Ҫ<><D2AA>ȡ<EFBFBD><C8A1><see cref="GameModule"/></returns>
|
||||
/// <remarks><3E><><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA>ȡ<EFBFBD><C8A1><see cref="GameModule"/><3E><><EFBFBD><EFBFBD><EFBFBD>ڣ<EFBFBD><DAA3><EFBFBD><EFBFBD>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><see cref="GameModule"/>ʵ<><CAB5><EFBFBD><EFBFBD></remarks>
|
||||
private static GameModule GetModule(Type moduleType, int stackLayer = 0)
|
||||
{
|
||||
foreach (GameModule module in s_GameFrameworkModules)
|
||||
{
|
||||
if (module.GetType() == moduleType)
|
||||
{
|
||||
return module;
|
||||
}
|
||||
}
|
||||
|
||||
return CreateModule(moduleType, stackLayer + 1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <20><>ȡ<EFBFBD><C8A1>Ϸ<EFBFBD><CFB7><EFBFBD><EFBFBD>ģ<EFBFBD>顣
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Ҫ<><D2AA>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>Ϸ<EFBFBD><CFB7><EFBFBD><EFBFBD>ģ<EFBFBD><C4A3><EFBFBD><EFBFBD><EFBFBD>͡<EFBFBD></typeparam>
|
||||
/// <returns>Ҫ<><D2AA>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>Ϸ<EFBFBD><CFB7><EFBFBD><EFBFBD>ģ<EFBFBD>顣</returns>
|
||||
/// <remarks><3E><><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>Ϸ<EFBFBD><CFB7><EFBFBD><EFBFBD>ģ<EFBFBD>鲻<EFBFBD><E9B2BB><EFBFBD>ڣ<EFBFBD><DAA3><EFBFBD><EFBFBD>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϸ<EFBFBD><CFB7><EFBFBD><EFBFBD>ģ<EFBFBD>顣</remarks>
|
||||
public static T GetModule<T>() where T : GameModule
|
||||
{
|
||||
return (T)GetModule(typeof(T));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <20>رղ<D8B1><D5B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϸ<EFBFBD><CFB7><EFBFBD><EFBFBD>ģ<EFBFBD>顣
|
||||
/// </summary>
|
||||
public static void Shutdown()
|
||||
{
|
||||
for (var current = s_GameFrameworkModules.Last; current != null; current = current.Previous)
|
||||
{
|
||||
current.Value.Shutdown();
|
||||
}
|
||||
|
||||
s_GameFrameworkModules.Clear();
|
||||
ReferencePool.ClearAll();
|
||||
Utility.Marshal.FreeCachedHGlobal();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϸ<EFBFBD><CFB7><EFBFBD><EFBFBD>ģ<EFBFBD><C4A3><EFBFBD><EFBFBD>ѯ<EFBFBD><D1AF>
|
||||
/// </summary>
|
||||
/// <param name="elapseSeconds"><3E><EFBFBD><DFBC><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD>䣬<EFBFBD><E4A3AC><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA>λ<EFBFBD><CEBB></param>
|
||||
/// <param name="realElapseSeconds"><3E><>ʵ<EFBFBD><CAB5><EFBFBD><EFBFBD>ʱ<EFBFBD>䣬<EFBFBD><E4A3AC><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA>λ<EFBFBD><CEBB></param>
|
||||
public static void Update(float elapseSeconds, float realElapseSeconds)
|
||||
{
|
||||
foreach (var module in s_GameFrameworkModules)
|
||||
{
|
||||
module.Update(elapseSeconds, realElapseSeconds);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Convention/[Architecture]/Architecture.cs.meta
Normal file
11
Convention/[Architecture]/Architecture.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 07141d7da2b1cc74dbfaf880734228dd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Convention/[Architecture]/Modules.meta
Normal file
8
Convention/[Architecture]/Modules.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 591a2c63cd01a22408284eeaa811e930
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
17
Convention/[Architecture]/Modules/ConfigManager.cs
Normal file
17
Convention/[Architecture]/Modules/ConfigManager.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Convention.Experimental.Modules
|
||||
{
|
||||
public class ConfigManager : PublicType.GameModule
|
||||
{
|
||||
public readonly ProjectConfig m_ProjectConfig = new();
|
||||
public bool IsSavePropertiesWhenShutdown = false;
|
||||
|
||||
internal override void Shutdown()
|
||||
{
|
||||
if (IsSavePropertiesWhenShutdown)
|
||||
m_ProjectConfig.SaveProperties();
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Convention/[Architecture]/Modules/ConfigManager.cs.meta
Normal file
11
Convention/[Architecture]/Modules/ConfigManager.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: eae9830d96a5f184b832846bf67c4b59
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
74
Convention/[Architecture]/Modules/ObjectPoolManager.cs
Normal file
74
Convention/[Architecture]/Modules/ObjectPoolManager.cs
Normal file
@@ -0,0 +1,74 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Convention.Experimental.Modules
|
||||
{
|
||||
public class ObjectPoolManager : PublicType.GameModule
|
||||
{
|
||||
public interface IPawn
|
||||
{
|
||||
void Release();
|
||||
}
|
||||
|
||||
private readonly Dictionary<GameObject, Stack<GameObject>> ObjectPools = new();
|
||||
private readonly Dictionary<GameObject, GameObject> LeavePoolObjects = new();
|
||||
|
||||
public GameObject Spawn(GameObject prefab)
|
||||
{
|
||||
if (!ObjectPools.ContainsKey(prefab))
|
||||
{
|
||||
ObjectPools[prefab] = new();
|
||||
}
|
||||
var pool = ObjectPools[prefab];
|
||||
GameObject instance;
|
||||
if (pool.Count > 0)
|
||||
{
|
||||
instance = pool.Pop();
|
||||
instance.SetActive(true);
|
||||
instance.transform.SetParent(null);
|
||||
}
|
||||
else
|
||||
{
|
||||
instance = GameObject.Instantiate(prefab);
|
||||
}
|
||||
LeavePoolObjects[instance] = prefab;
|
||||
return instance;
|
||||
}
|
||||
|
||||
public void BackPool(GameObject instance)
|
||||
{
|
||||
if(LeavePoolObjects.TryGetValue(instance,out var prefab))
|
||||
{
|
||||
var releaser = instance.GetComponents<IPawn>();
|
||||
foreach (var r in releaser)
|
||||
{
|
||||
r.Release();
|
||||
}
|
||||
instance.SetActive(false);
|
||||
instance.transform.SetParent(ConventionUtility.Singleton.transform);
|
||||
ObjectPools[prefab].Push(instance);
|
||||
LeavePoolObjects.Remove(instance);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new PublicType.GameException("This object does not belong to any pool.");
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearPool(GameObject prefab)
|
||||
{
|
||||
if (ObjectPools.TryGetValue(prefab, out var pool))
|
||||
{
|
||||
while (pool.Count > 0)
|
||||
{
|
||||
var instance = pool.Pop();
|
||||
GameObject.Destroy(instance);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new PublicType.GameException("This pool does not exist.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Convention/[Architecture]/Modules/ObjectPoolManager.cs.meta
Normal file
11
Convention/[Architecture]/Modules/ObjectPoolManager.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 912f3c1afd07d714d83cd965f3a0f7e4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Convention/[Architecture]/PublicType.meta
Normal file
8
Convention/[Architecture]/PublicType.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 997615a04b8d2844aa27b8d212998bd6
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
52
Convention/[Architecture]/PublicType/GameException.cs
Normal file
52
Convention/[Architecture]/PublicType/GameException.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.Serialization;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Convention.Experimental.PublicType
|
||||
{
|
||||
/// <summary>
|
||||
/// <20><>Ϸ<EFBFBD><CFB7><EFBFBD><EFBFBD><EFBFBD>쳣<EFBFBD>ࡣ
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class GameException : Exception
|
||||
{
|
||||
/// <summary>
|
||||
/// <20><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD>Ϸ<EFBFBD><CFB7><EFBFBD><EFBFBD><EFBFBD>쳣<EFBFBD><ECB3A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><CAB5><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
public GameException()
|
||||
: base()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ʹ<><CAB9>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><CFA2>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD>Ϸ<EFBFBD><CFB7><EFBFBD><EFBFBD><EFBFBD>쳣<EFBFBD><ECB3A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><CAB5><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
/// <param name="message"><3E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><CFA2></param>
|
||||
public GameException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ʹ<><CAB9>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD>쳣ԭ<ECB3A3><D4AD><EFBFBD><EFBFBD><EFBFBD>ڲ<EFBFBD><DAB2>쳣<EFBFBD><ECB3A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD>Ϸ<EFBFBD><CFB7><EFBFBD><EFBFBD><EFBFBD>쳣<EFBFBD><ECB3A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><CAB5><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
/// <param name="message"><3E><><EFBFBD><EFBFBD><EFBFBD>쳣ԭ<ECB3A3><D4AD><EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><CFA2></param>
|
||||
/// <param name="innerException"><3E><><EFBFBD>µ<EFBFBD>ǰ<EFBFBD>쳣<EFBFBD><ECB3A3><EFBFBD>쳣<EFBFBD><ECB3A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD> innerException <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD>ã<EFBFBD><C3A3><EFBFBD><EFBFBD>ڴ<EFBFBD><DAB4><EFBFBD><EFBFBD>ڲ<EFBFBD><DAB2>쳣<EFBFBD><ECB3A3> catch <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD>쳣<EFBFBD><ECB3A3></param>
|
||||
public GameException(string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD>л<EFBFBD><D0BB><EFBFBD><EFBFBD>ݳ<EFBFBD>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD>Ϸ<EFBFBD><CFB7><EFBFBD><EFBFBD><EFBFBD>쳣<EFBFBD><ECB3A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><CAB5><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
/// <param name="info"><3E><><EFBFBD><EFBFBD><EFBFBD>й<EFBFBD><D0B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>쳣<EFBFBD><ECB3A3><EFBFBD><EFBFBD><EFBFBD>л<EFBFBD><D0BB>Ķ<EFBFBD><C4B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݡ<EFBFBD></param>
|
||||
/// <param name="context"><3E><><EFBFBD><EFBFBD><EFBFBD>й<EFBFBD>Դ<EFBFBD><D4B4>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><CFA2></param>
|
||||
protected GameException(SerializationInfo info, StreamingContext context)
|
||||
: base(info, context)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Convention/[Architecture]/PublicType/GameException.cs.meta
Normal file
11
Convention/[Architecture]/PublicType/GameException.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 93a229364c4ce134aa9548ad57f9e790
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
40
Convention/[Architecture]/PublicType/GameModule.cs
Normal file
40
Convention/[Architecture]/PublicType/GameModule.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Convention.Experimental.PublicType
|
||||
{
|
||||
/// <summary>
|
||||
/// <20><>Ϸ<EFBFBD><CFB7><EFBFBD><EFBFBD>ģ<EFBFBD><C4A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
public abstract class GameModule
|
||||
{
|
||||
/// <summary>
|
||||
/// <20><>ȡ<EFBFBD><C8A1>Ϸ<EFBFBD><CFB7><EFBFBD><EFBFBD>ģ<EFBFBD><C4A3><EFBFBD><EFBFBD><EFBFBD>ȼ<EFBFBD>
|
||||
/// </summary>
|
||||
/// <remarks><3E><><EFBFBD>ȼ<EFBFBD><C8BC>ϸߵ<CFB8>ģ<EFBFBD><C4A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѯ<EFBFBD><D1AF><EFBFBD><EFBFBD><EFBFBD>ȼ<EFBFBD><C8BC>ϵ͵<CFB5>ģ<EFBFBD><C4A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD><D0B6></remarks>
|
||||
internal virtual int Priority
|
||||
{
|
||||
get
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <20><>Ϸ<EFBFBD><CFB7><EFBFBD><EFBFBD>ģ<EFBFBD><C4A3><EFBFBD><EFBFBD>ѯ
|
||||
/// </summary>
|
||||
/// <param name="elapseSeconds"><3E><EFBFBD><DFBC><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD>䣬<EFBFBD><E4A3AC><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA>λ</param>
|
||||
/// <param name="realElapseSeconds"><3E><>ʵ<EFBFBD><CAB5><EFBFBD><EFBFBD>ʱ<EFBFBD>䣬<EFBFBD><E4A3AC><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA>λ</param>
|
||||
internal virtual void Update(float elapseSeconds, float realElapseSeconds) { }
|
||||
|
||||
/// <summary>
|
||||
/// <20>رղ<D8B1><D5B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϸ<EFBFBD><CFB7><EFBFBD><EFBFBD>ģ<EFBFBD><C4A3>
|
||||
/// </summary>
|
||||
internal virtual void Shutdown() { }
|
||||
|
||||
/// <summary>
|
||||
/// ǰ<><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϸ<EFBFBD><CFB7><EFBFBD><EFBFBD>ģ<EFBFBD><C4A3><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD>
|
||||
/// </summary>
|
||||
internal virtual IEnumerable<Type> Dependences() => Array.Empty<Type>();
|
||||
}
|
||||
}
|
||||
11
Convention/[Architecture]/PublicType/GameModule.cs.meta
Normal file
11
Convention/[Architecture]/PublicType/GameModule.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2f8a535a831e2c44097dcac4a87db7ff
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
455
Convention/[Architecture]/PublicType/LinkedCacheList.cs
Normal file
455
Convention/[Architecture]/PublicType/LinkedCacheList.cs
Normal file
@@ -0,0 +1,455 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Convention.Experimental.PublicType
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 附带有缓存机制的链表类。
|
||||
/// </summary>
|
||||
/// <typeparam name="T">指定链表的元素类型。</typeparam>
|
||||
public sealed class LinkedCacheList<T> : ICollection<T>, IEnumerable<T>, ICollection, IEnumerable
|
||||
{
|
||||
private readonly LinkedList<T> m_LinkedList;
|
||||
/// <summary>
|
||||
/// 之所以需要这套缓存机制,主要有三点好处:
|
||||
/// <list type="bullet">减少 GC 压力:大量频繁的插入/删除会产生很多短生命周期的节点对象,通过复用可以显著降低托管堆的分配与回收次数</list>
|
||||
/// <list type="bullet">提升性能:避免频繁 new 和 GC,能减少停顿时间,提高链表在高频操作场景下的吞吐</list>
|
||||
/// <list type="bullet">便于观察与管理:类中还提供了 CachedNodeCount 方便调试统计缓存规模,必要时可通过 ClearCachedNodes 主动释放</list>
|
||||
/// 适用场景是节点使用模式“高频增删但总量有限”,此时缓存能稳定性能;若链表规模始终在增长且很少释放,缓存收益会较低。
|
||||
/// </summary>
|
||||
private readonly Queue<LinkedListNode<T>> m_CachedNodes;
|
||||
|
||||
/// <summary>
|
||||
/// 初始化游戏框架链表类的新实例。
|
||||
/// </summary>
|
||||
public LinkedCacheList()
|
||||
{
|
||||
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="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 GameException("First is invalid.");
|
||||
}
|
||||
|
||||
m_LinkedList.RemoveFirst();
|
||||
ReleaseNode(first);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 移除位于链表结尾处的结点。
|
||||
/// </summary>
|
||||
public void RemoveLast()
|
||||
{
|
||||
LinkedListNode<T> last = m_LinkedList.Last;
|
||||
if (last == null)
|
||||
{
|
||||
throw new GameException("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 GameException("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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Convention/[Architecture]/PublicType/LinkedCacheList.cs.meta
Normal file
11
Convention/[Architecture]/PublicType/LinkedCacheList.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 34c26073576fd3b488f2b547e7e8eb0a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
491
Convention/[Architecture]/PublicType/ReferencePool.cs
Normal file
491
Convention/[Architecture]/PublicType/ReferencePool.cs
Normal file
@@ -0,0 +1,491 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using Unity.VisualScripting;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Convention.Experimental.PublicType
|
||||
{
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD>ýӿڡ<D3BF>
|
||||
/// </summary>
|
||||
public interface IReference
|
||||
{
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>á<EFBFBD>
|
||||
/// </summary>
|
||||
void Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD>ó<EFBFBD>
|
||||
/// </summary>
|
||||
public static partial class ReferencePool
|
||||
{
|
||||
private static bool m_EnableStrictCheck = false;
|
||||
|
||||
/// <summary>
|
||||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD>ǿ<EFBFBD>Ƽ<EFBFBD><C6BC><EFBFBD>
|
||||
/// </summary>
|
||||
public static bool EnableStrictCheck
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_EnableStrictCheck;
|
||||
}
|
||||
set
|
||||
{
|
||||
m_EnableStrictCheck = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private sealed class ReferenceCollection
|
||||
{
|
||||
private readonly Queue<IReference> m_References;
|
||||
private readonly Type m_ReferenceType;
|
||||
private int m_UsingReferenceCount;
|
||||
private int m_AcquireReferenceCount;
|
||||
private int m_ReleaseReferenceCount;
|
||||
private int m_AddReferenceCount;
|
||||
private int m_RemoveReferenceCount;
|
||||
|
||||
public ReferenceCollection(Type referenceType)
|
||||
{
|
||||
m_References = new Queue<IReference>();
|
||||
m_ReferenceType = referenceType;
|
||||
m_UsingReferenceCount = 0;
|
||||
m_AcquireReferenceCount = 0;
|
||||
m_ReleaseReferenceCount = 0;
|
||||
m_AddReferenceCount = 0;
|
||||
m_RemoveReferenceCount = 0;
|
||||
}
|
||||
|
||||
public Type ReferenceType
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_ReferenceType;
|
||||
}
|
||||
}
|
||||
|
||||
public int UnusedReferenceCount
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_References.Count;
|
||||
}
|
||||
}
|
||||
|
||||
public int UsingReferenceCount
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_UsingReferenceCount;
|
||||
}
|
||||
}
|
||||
|
||||
public int AcquireReferenceCount
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_AcquireReferenceCount;
|
||||
}
|
||||
}
|
||||
|
||||
public int ReleaseReferenceCount
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_ReleaseReferenceCount;
|
||||
}
|
||||
}
|
||||
|
||||
public int AddReferenceCount
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_AddReferenceCount;
|
||||
}
|
||||
}
|
||||
|
||||
public int RemoveReferenceCount
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_RemoveReferenceCount;
|
||||
}
|
||||
}
|
||||
|
||||
public T Acquire<T>() where T : class, IReference, new()
|
||||
{
|
||||
if (typeof(T) != m_ReferenceType)
|
||||
{
|
||||
throw new GameException("Type is invalid.");
|
||||
}
|
||||
|
||||
m_UsingReferenceCount++;
|
||||
m_AcquireReferenceCount++;
|
||||
lock (m_References)
|
||||
{
|
||||
if (m_References.Count > 0)
|
||||
{
|
||||
return (T)m_References.Dequeue();
|
||||
}
|
||||
}
|
||||
|
||||
m_AddReferenceCount++;
|
||||
return new T();
|
||||
}
|
||||
|
||||
public IReference Acquire()
|
||||
{
|
||||
m_UsingReferenceCount++;
|
||||
m_AcquireReferenceCount++;
|
||||
lock (m_References)
|
||||
{
|
||||
if (m_References.Count > 0)
|
||||
{
|
||||
return m_References.Dequeue();
|
||||
}
|
||||
}
|
||||
|
||||
m_AddReferenceCount++;
|
||||
return (IReference)Activator.CreateInstance(m_ReferenceType);
|
||||
}
|
||||
|
||||
public void Release(IReference reference)
|
||||
{
|
||||
reference.Clear();
|
||||
lock (m_References)
|
||||
{
|
||||
if (m_EnableStrictCheck && m_References.Contains(reference))
|
||||
{
|
||||
throw new GameException("The reference has been released.");
|
||||
}
|
||||
|
||||
m_References.Enqueue(reference);
|
||||
}
|
||||
|
||||
m_ReleaseReferenceCount++;
|
||||
m_UsingReferenceCount--;
|
||||
}
|
||||
|
||||
public void Add<T>(int count) where T : class, IReference, new()
|
||||
{
|
||||
if (typeof(T) != m_ReferenceType)
|
||||
{
|
||||
throw new GameException("Type is invalid.");
|
||||
}
|
||||
|
||||
lock (m_References)
|
||||
{
|
||||
m_AddReferenceCount += count;
|
||||
while (count-- > 0)
|
||||
{
|
||||
m_References.Enqueue(new T());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Add(int count)
|
||||
{
|
||||
lock (m_References)
|
||||
{
|
||||
m_AddReferenceCount += count;
|
||||
while (count-- > 0)
|
||||
{
|
||||
m_References.Enqueue((IReference)Activator.CreateInstance(m_ReferenceType));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Remove(int count)
|
||||
{
|
||||
lock (m_References)
|
||||
{
|
||||
if (count > m_References.Count)
|
||||
{
|
||||
count = m_References.Count;
|
||||
}
|
||||
|
||||
m_RemoveReferenceCount += count;
|
||||
while (count-- > 0)
|
||||
{
|
||||
m_References.Dequeue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveAll()
|
||||
{
|
||||
lock (m_References)
|
||||
{
|
||||
m_RemoveReferenceCount += m_References.Count;
|
||||
m_References.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly Dictionary<Type, ReferenceCollection> s_ReferenceCollections = new();
|
||||
|
||||
/// <summary>
|
||||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD>óص<C3B3><D8B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
public static int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
return s_ReferenceCollections.Count;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD>ó<EFBFBD><C3B3><EFBFBD>Ϣ
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Auto)]
|
||||
public readonly struct ReferencePoolInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD>ó<EFBFBD><C3B3><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
public readonly Type Type;
|
||||
/// <summary>
|
||||
/// δʹ<CEB4><CAB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
public readonly int UnusedReferenceCount;
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
public readonly int UsingReferenceCount;
|
||||
/// <summary>
|
||||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
public readonly int AcquireReferenceCount;
|
||||
/// <summary>
|
||||
/// <20>黹<EFBFBD><E9BBB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
public readonly int ReleaseReferenceCount;
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
public readonly int AddReferenceCount;
|
||||
/// <summary>
|
||||
/// <20>Ƴ<EFBFBD><C6B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
public readonly int RemoveReferenceCount;
|
||||
|
||||
/// <summary>
|
||||
/// <20><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD>ó<EFBFBD><C3B3><EFBFBD>Ϣ<EFBFBD><CFA2><EFBFBD><EFBFBD>ʵ<EFBFBD><CAB5><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
/// <param name="type"><3E><><EFBFBD>ó<EFBFBD><C3B3><EFBFBD><EFBFBD>͡<EFBFBD></param>
|
||||
/// <param name="unusedReferenceCount">δʹ<CEB4><CAB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD></param>
|
||||
/// <param name="usingReferenceCount"><3E><><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD></param>
|
||||
/// <param name="acquireReferenceCount"><3E><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD></param>
|
||||
/// <param name="releaseReferenceCount"><3E>黹<EFBFBD><E9BBB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD></param>
|
||||
/// <param name="addReferenceCount"><3E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD></param>
|
||||
/// <param name="removeReferenceCount"><3E>Ƴ<EFBFBD><C6B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD></param>
|
||||
public ReferencePoolInfo(Type type,
|
||||
int unusedReferenceCount,
|
||||
int usingReferenceCount,
|
||||
int acquireReferenceCount,
|
||||
int releaseReferenceCount,
|
||||
int addReferenceCount,
|
||||
int removeReferenceCount)
|
||||
{
|
||||
this.Type = type;
|
||||
this.UnusedReferenceCount = unusedReferenceCount;
|
||||
this.UsingReferenceCount = usingReferenceCount;
|
||||
this.AcquireReferenceCount = acquireReferenceCount;
|
||||
this.ReleaseReferenceCount = releaseReferenceCount;
|
||||
this.AddReferenceCount = addReferenceCount;
|
||||
this.RemoveReferenceCount = removeReferenceCount;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>óص<C3B3><D8B5><EFBFBD>Ϣ
|
||||
/// </summary>
|
||||
/// <returns><3E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>óص<C3B3><D8B5><EFBFBD>Ϣ</returns>
|
||||
public static ReferencePoolInfo[] GetAllReferencePoolInfos()
|
||||
{
|
||||
int index = 0;
|
||||
ReferencePoolInfo[] results = null;
|
||||
|
||||
lock (s_ReferenceCollections)
|
||||
{
|
||||
results = new ReferencePoolInfo[s_ReferenceCollections.Count];
|
||||
foreach (var (key,value) in s_ReferenceCollections)
|
||||
{
|
||||
results[index++] = new ReferencePoolInfo(key,
|
||||
value.UnusedReferenceCount,
|
||||
value.UsingReferenceCount,
|
||||
value.AcquireReferenceCount,
|
||||
value.ReleaseReferenceCount,
|
||||
value.AddReferenceCount,
|
||||
value.RemoveReferenceCount);
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ó<EFBFBD>
|
||||
/// </summary>
|
||||
public static void ClearAll()
|
||||
{
|
||||
lock (s_ReferenceCollections)
|
||||
{
|
||||
foreach (var (_, value) in s_ReferenceCollections)
|
||||
{
|
||||
value.RemoveAll();
|
||||
}
|
||||
|
||||
s_ReferenceCollections.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
private static ReferenceCollection GetReferenceCollection(Type referenceType)
|
||||
{
|
||||
if (referenceType == null)
|
||||
{
|
||||
throw new GameException("ReferenceType is invalid.");
|
||||
}
|
||||
|
||||
ReferenceCollection referenceCollection = null;
|
||||
lock (s_ReferenceCollections)
|
||||
{
|
||||
if (!s_ReferenceCollections.TryGetValue(referenceType, out referenceCollection))
|
||||
{
|
||||
referenceCollection = new ReferenceCollection(referenceType);
|
||||
s_ReferenceCollections.Add(referenceType, referenceCollection);
|
||||
}
|
||||
}
|
||||
|
||||
return referenceCollection;
|
||||
}
|
||||
|
||||
private static void InternalCheckReferenceType(Type referenceType)
|
||||
{
|
||||
if (!m_EnableStrictCheck)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (referenceType == null)
|
||||
{
|
||||
throw new GameException("Reference type is invalid.");
|
||||
}
|
||||
|
||||
if (!referenceType.IsClass || referenceType.IsAbstract)
|
||||
{
|
||||
throw new GameException("Reference type is not a non-abstract class type.");
|
||||
}
|
||||
|
||||
if (!typeof(IReference).IsAssignableFrom(referenceType))
|
||||
{
|
||||
throw new GameException($"Reference type '{referenceType.FullName}' is invalid.");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD>óػ<C3B3>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
/// <param name="referenceType"><3E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD></param>
|
||||
/// <returns><3E><><EFBFBD><EFBFBD></returns>
|
||||
public static IReference Acquire(Type referenceType)
|
||||
{
|
||||
InternalCheckReferenceType(referenceType);
|
||||
return GetReferenceCollection(referenceType).Acquire();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD>óػ<C3B3>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
/// <typeparam name="T"><3E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD></typeparam>
|
||||
/// <returns><3E><><EFBFBD><EFBFBD></returns>
|
||||
public static T Acquire<T>() where T : class, IReference, new()
|
||||
{
|
||||
return GetReferenceCollection(typeof(T)).Acquire<T>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD>ù黹<C3B9><E9BBB9><EFBFBD>ó<EFBFBD>
|
||||
/// </summary>
|
||||
/// <param name="reference"><3E><><EFBFBD><EFBFBD></param>
|
||||
public static void Release(IReference reference)
|
||||
{
|
||||
if (reference == null)
|
||||
{
|
||||
throw new GameException("Reference is invalid.");
|
||||
}
|
||||
|
||||
Type referenceType = reference.GetType();
|
||||
InternalCheckReferenceType(referenceType);
|
||||
GetReferenceCollection(referenceType).Release(reference);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD>ó<EFBFBD><C3B3><EFBFBD><EFBFBD><D7B7>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
/// <typeparam name="T"><3E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD></typeparam>
|
||||
/// <param name="count"><><D7B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD></param>
|
||||
public static void Add<T>(int count) where T : class, IReference, new()
|
||||
{
|
||||
GetReferenceCollection(typeof(T)).Add<T>(count);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD>ó<EFBFBD><C3B3><EFBFBD><EFBFBD><D7B7>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
/// <param name="referenceType"><3E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD></param>
|
||||
/// <param name="count"><><D7B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD></param>
|
||||
public static void Add(Type referenceType, int count)
|
||||
{
|
||||
InternalCheckReferenceType(referenceType);
|
||||
GetReferenceCollection(referenceType).Add(count);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD>ó<EFBFBD><C3B3><EFBFBD><EFBFBD>Ƴ<EFBFBD>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
/// <typeparam name="T"><3E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD></typeparam>
|
||||
/// <param name="count"><3E>Ƴ<EFBFBD><C6B3><EFBFBD><EFBFBD><EFBFBD></param>
|
||||
public static void Remove<T>(int count) where T : class, IReference
|
||||
{
|
||||
GetReferenceCollection(typeof(T)).Remove(count);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD>ó<EFBFBD><C3B3><EFBFBD><EFBFBD>Ƴ<EFBFBD>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
/// <param name="referenceType"><3E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD></param>
|
||||
/// <param name="count"><3E>Ƴ<EFBFBD><C6B3><EFBFBD><EFBFBD><EFBFBD></param>
|
||||
public static void Remove(Type referenceType, int count)
|
||||
{
|
||||
InternalCheckReferenceType(referenceType);
|
||||
GetReferenceCollection(referenceType).Remove(count);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD>ó<EFBFBD><C3B3><EFBFBD><EFBFBD>Ƴ<EFBFBD><C6B3><EFBFBD><EFBFBD>е<EFBFBD><D0B5><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
/// <typeparam name="T"><3E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD></typeparam>
|
||||
public static void RemoveAll<T>() where T : class, IReference
|
||||
{
|
||||
GetReferenceCollection(typeof(T)).RemoveAll();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD>ó<EFBFBD><C3B3><EFBFBD><EFBFBD>Ƴ<EFBFBD><C6B3><EFBFBD><EFBFBD>е<EFBFBD><D0B5><EFBFBD><EFBFBD>á<EFBFBD>
|
||||
/// </summary>
|
||||
/// <param name="referenceType"><3E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>͡<EFBFBD></param>
|
||||
public static void RemoveAll(Type referenceType)
|
||||
{
|
||||
InternalCheckReferenceType(referenceType);
|
||||
GetReferenceCollection(referenceType).RemoveAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Convention/[Architecture]/PublicType/ReferencePool.cs.meta
Normal file
11
Convention/[Architecture]/PublicType/ReferencePool.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7a8ec3e4cc6e7e242b158fc02010c774
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -421,4 +421,4 @@ namespace Convention
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -424,6 +424,245 @@ namespace Convention
|
||||
{
|
||||
return DateTime.Now.ToString(format);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Marshal 相关的实用函数。
|
||||
/// </summary>
|
||||
public static class Marshal
|
||||
{
|
||||
|
||||
[Serializable]
|
||||
public class MarshalException : Exception
|
||||
{
|
||||
public MarshalException() { }
|
||||
public MarshalException(string message) : base(message) { }
|
||||
public MarshalException(string message, Exception inner) : base(message, inner) { }
|
||||
protected MarshalException(
|
||||
System.Runtime.Serialization.SerializationInfo info,
|
||||
System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
|
||||
}
|
||||
|
||||
private const int BlockSize = 1024 * 4;
|
||||
private static IntPtr s_CachedHGlobalPtr = IntPtr.Zero;
|
||||
private static int s_CachedHGlobalSize = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 获取缓存的从进程的非托管内存中分配的内存的大小。
|
||||
/// </summary>
|
||||
public static int CachedHGlobalSize
|
||||
{
|
||||
get
|
||||
{
|
||||
return s_CachedHGlobalSize;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 确保从进程的非托管内存中分配足够大小的内存并缓存。
|
||||
/// </summary>
|
||||
/// <param name="ensureSize">要确保从进程的非托管内存中分配内存的大小。</param>
|
||||
public static void EnsureCachedHGlobalSize(int ensureSize)
|
||||
{
|
||||
if (ensureSize < 0)
|
||||
{
|
||||
throw new MarshalException("Ensure size is invalid.");
|
||||
}
|
||||
|
||||
if (s_CachedHGlobalPtr == IntPtr.Zero || s_CachedHGlobalSize < ensureSize)
|
||||
{
|
||||
FreeCachedHGlobal();
|
||||
int size = (ensureSize - 1 + BlockSize) / BlockSize * BlockSize;
|
||||
s_CachedHGlobalPtr = System.Runtime.InteropServices.Marshal.AllocHGlobal(size);
|
||||
s_CachedHGlobalSize = size;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 释放缓存的从进程的非托管内存中分配的内存。
|
||||
/// </summary>
|
||||
public static void FreeCachedHGlobal()
|
||||
{
|
||||
if (s_CachedHGlobalPtr != IntPtr.Zero)
|
||||
{
|
||||
System.Runtime.InteropServices.Marshal.FreeHGlobal(s_CachedHGlobalPtr);
|
||||
s_CachedHGlobalPtr = IntPtr.Zero;
|
||||
s_CachedHGlobalSize = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将数据从对象转换为二进制流。
|
||||
/// </summary>
|
||||
/// <typeparam name="T">要转换的对象的类型。</typeparam>
|
||||
/// <param name="structure">要转换的对象。</param>
|
||||
/// <returns>存储转换结果的二进制流。</returns>
|
||||
public static byte[] StructureToBytes<T>(T structure)
|
||||
{
|
||||
return StructureToBytes(structure, System.Runtime.InteropServices.Marshal.SizeOf(typeof(T)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将数据从对象转换为二进制流。
|
||||
/// </summary>
|
||||
/// <typeparam name="T">要转换的对象的类型。</typeparam>
|
||||
/// <param name="structure">要转换的对象。</param>
|
||||
/// <param name="structureSize">要转换的对象的大小。</param>
|
||||
/// <returns>存储转换结果的二进制流。</returns>
|
||||
internal static byte[] StructureToBytes<T>(T structure, int structureSize)
|
||||
{
|
||||
if (structureSize < 0)
|
||||
{
|
||||
throw new MarshalException("Structure size is invalid.");
|
||||
}
|
||||
|
||||
EnsureCachedHGlobalSize(structureSize);
|
||||
System.Runtime.InteropServices.Marshal.StructureToPtr(structure, s_CachedHGlobalPtr, true);
|
||||
byte[] result = new byte[structureSize];
|
||||
System.Runtime.InteropServices.Marshal.Copy(s_CachedHGlobalPtr, result, 0, structureSize);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将数据从对象转换为二进制流。
|
||||
/// </summary>
|
||||
/// <typeparam name="T">要转换的对象的类型。</typeparam>
|
||||
/// <param name="structure">要转换的对象。</param>
|
||||
/// <param name="result">存储转换结果的二进制流。</param>
|
||||
public static void StructureToBytes<T>(T structure, byte[] result)
|
||||
{
|
||||
StructureToBytes(structure, System.Runtime.InteropServices.Marshal.SizeOf(typeof(T)), result, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将数据从对象转换为二进制流。
|
||||
/// </summary>
|
||||
/// <typeparam name="T">要转换的对象的类型。</typeparam>
|
||||
/// <param name="structure">要转换的对象。</param>
|
||||
/// <param name="structureSize">要转换的对象的大小。</param>
|
||||
/// <param name="result">存储转换结果的二进制流。</param>
|
||||
internal static void StructureToBytes<T>(T structure, int structureSize, byte[] result)
|
||||
{
|
||||
StructureToBytes(structure, structureSize, result, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将数据从对象转换为二进制流。
|
||||
/// </summary>
|
||||
/// <typeparam name="T">要转换的对象的类型。</typeparam>
|
||||
/// <param name="structure">要转换的对象。</param>
|
||||
/// <param name="result">存储转换结果的二进制流。</param>
|
||||
/// <param name="startIndex">写入存储转换结果的二进制流的起始位置。</param>
|
||||
public static void StructureToBytes<T>(T structure, byte[] result, int startIndex)
|
||||
{
|
||||
StructureToBytes(structure, System.Runtime.InteropServices.Marshal.SizeOf(typeof(T)), result, startIndex);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将数据从对象转换为二进制流。
|
||||
/// </summary>
|
||||
/// <typeparam name="T">要转换的对象的类型。</typeparam>
|
||||
/// <param name="structure">要转换的对象。</param>
|
||||
/// <param name="structureSize">要转换的对象的大小。</param>
|
||||
/// <param name="result">存储转换结果的二进制流。</param>
|
||||
/// <param name="startIndex">写入存储转换结果的二进制流的起始位置。</param>
|
||||
internal static void StructureToBytes<T>(T structure, int structureSize, byte[] result, int startIndex)
|
||||
{
|
||||
if (structureSize < 0)
|
||||
{
|
||||
throw new MarshalException("Structure size is invalid.");
|
||||
}
|
||||
|
||||
if (result == null)
|
||||
{
|
||||
throw new MarshalException("Result is invalid.");
|
||||
}
|
||||
|
||||
if (startIndex < 0)
|
||||
{
|
||||
throw new MarshalException("Start index is invalid.");
|
||||
}
|
||||
|
||||
if (startIndex + structureSize > result.Length)
|
||||
{
|
||||
throw new MarshalException("Result length is not enough.");
|
||||
}
|
||||
|
||||
EnsureCachedHGlobalSize(structureSize);
|
||||
System.Runtime.InteropServices.Marshal.StructureToPtr(structure, s_CachedHGlobalPtr, true);
|
||||
System.Runtime.InteropServices.Marshal.Copy(s_CachedHGlobalPtr, result, startIndex, structureSize);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将数据从二进制流转换为对象。
|
||||
/// </summary>
|
||||
/// <typeparam name="T">要转换的对象的类型。</typeparam>
|
||||
/// <param name="buffer">要转换的二进制流。</param>
|
||||
/// <returns>存储转换结果的对象。</returns>
|
||||
public static T BytesToStructure<T>(byte[] buffer)
|
||||
{
|
||||
return BytesToStructure<T>(System.Runtime.InteropServices.Marshal.SizeOf(typeof(T)), buffer, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将数据从二进制流转换为对象。
|
||||
/// </summary>
|
||||
/// <typeparam name="T">要转换的对象的类型。</typeparam>
|
||||
/// <param name="buffer">要转换的二进制流。</param>
|
||||
/// <param name="startIndex">读取要转换的二进制流的起始位置。</param>
|
||||
/// <returns>存储转换结果的对象。</returns>
|
||||
public static T BytesToStructure<T>(byte[] buffer, int startIndex)
|
||||
{
|
||||
return BytesToStructure<T>(System.Runtime.InteropServices.Marshal.SizeOf(typeof(T)), buffer, startIndex);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将数据从二进制流转换为对象。
|
||||
/// </summary>
|
||||
/// <typeparam name="T">要转换的对象的类型。</typeparam>
|
||||
/// <param name="structureSize">要转换的对象的大小。</param>
|
||||
/// <param name="buffer">要转换的二进制流。</param>
|
||||
/// <returns>存储转换结果的对象。</returns>
|
||||
internal static T BytesToStructure<T>(int structureSize, byte[] buffer)
|
||||
{
|
||||
return BytesToStructure<T>(structureSize, buffer, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将数据从二进制流转换为对象。
|
||||
/// </summary>
|
||||
/// <typeparam name="T">要转换的对象的类型。</typeparam>
|
||||
/// <param name="structureSize">要转换的对象的大小。</param>
|
||||
/// <param name="buffer">要转换的二进制流。</param>
|
||||
/// <param name="startIndex">读取要转换的二进制流的起始位置。</param>
|
||||
/// <returns>存储转换结果的对象。</returns>
|
||||
internal static T BytesToStructure<T>(int structureSize, byte[] buffer, int startIndex)
|
||||
{
|
||||
if (structureSize < 0)
|
||||
{
|
||||
throw new MarshalException("Structure size is invalid.");
|
||||
}
|
||||
|
||||
if (buffer == null)
|
||||
{
|
||||
throw new MarshalException("Buffer is invalid.");
|
||||
}
|
||||
|
||||
if (startIndex < 0)
|
||||
{
|
||||
throw new MarshalException("Start index is invalid.");
|
||||
}
|
||||
|
||||
if (startIndex + structureSize > buffer.Length)
|
||||
{
|
||||
throw new MarshalException("Buffer length is not enough.");
|
||||
}
|
||||
|
||||
EnsureCachedHGlobalSize(structureSize);
|
||||
System.Runtime.InteropServices.Marshal.Copy(buffer, startIndex, s_CachedHGlobalPtr, structureSize);
|
||||
return (T)System.Runtime.InteropServices.Marshal.PtrToStructure(s_CachedHGlobalPtr, typeof(T));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1046,6 +1285,7 @@ namespace Convention
|
||||
}
|
||||
|
||||
private static CoroutineMonoStarterUtil CoroutineStarter;
|
||||
public static GameObject Singleton => CoroutineStarter.gameObject;
|
||||
|
||||
private class CoroutineMonoStarterUtil : MonoBehaviour
|
||||
{
|
||||
@@ -2232,3 +2472,10 @@ namespace Convention
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace Convention
|
||||
{
|
||||
public static partial class ConventionUtility
|
||||
{
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user