فهرست منبع

集成了sj的非托管容器库 https://github.com/susices/NativeCollection
TimerComponent.cs 跟 KService中的MultiMap换成非托管的

升级Unity版本到2021.3.29,打包测试通过

tanghai 2 سال پیش
والد
کامیت
2e1a03c2b6
56فایلهای تغییر یافته به همراه3778 افزوده شده و 469 حذف شده
  1. 4 0
      DotNet/ThirdParty/DotNet.ThirdParty.csproj
  2. 2 2
      Unity/Assets/Scripts/Core/Fiber/Module/Timer/TimerComponent.cs
  3. 1 1
      Unity/Assets/Scripts/Core/MultiMap.cs
  4. 2 2
      Unity/Assets/Scripts/Core/Network/KService.cs
  5. 0 248
      Unity/Assets/Scripts/Core/SortedCollection.cs
  6. 33 196
      Unity/Assets/Scripts/Loader/Plugins/HybridCLR/Generated/AOTGenericReferences.cs
  7. 6 3
      Unity/Assets/Scripts/Loader/Plugins/HybridCLR/Generated/link.xml
  8. 8 0
      Unity/Assets/Scripts/ThirdParty/NativeCollection.meta
  9. 96 0
      Unity/Assets/Scripts/ThirdParty/NativeCollection/HashSet.cs
  10. 1 1
      Unity/Assets/Scripts/ThirdParty/NativeCollection/HashSet.cs.meta
  11. 12 0
      Unity/Assets/Scripts/ThirdParty/NativeCollection/INativeCollectionClass.cs
  12. 11 0
      Unity/Assets/Scripts/ThirdParty/NativeCollection/INativeCollectionClass.cs.meta
  13. 120 0
      Unity/Assets/Scripts/ThirdParty/NativeCollection/List.cs
  14. 11 0
      Unity/Assets/Scripts/ThirdParty/NativeCollection/List.cs.meta
  15. 98 0
      Unity/Assets/Scripts/ThirdParty/NativeCollection/MultiMap.cs
  16. 11 0
      Unity/Assets/Scripts/ThirdParty/NativeCollection/MultiMap.cs.meta
  17. 70 0
      Unity/Assets/Scripts/ThirdParty/NativeCollection/NativeMemoryHelper.cs
  18. 11 0
      Unity/Assets/Scripts/ThirdParty/NativeCollection/NativeMemoryHelper.cs.meta
  19. 57 0
      Unity/Assets/Scripts/ThirdParty/NativeCollection/NativePool.cs
  20. 11 0
      Unity/Assets/Scripts/ThirdParty/NativeCollection/NativePool.cs.meta
  21. 88 0
      Unity/Assets/Scripts/ThirdParty/NativeCollection/Queue.cs
  22. 11 0
      Unity/Assets/Scripts/ThirdParty/NativeCollection/Queue.cs.meta
  23. 101 0
      Unity/Assets/Scripts/ThirdParty/NativeCollection/SortedSet.cs
  24. 11 0
      Unity/Assets/Scripts/ThirdParty/NativeCollection/SortedSet.cs.meta
  25. 88 0
      Unity/Assets/Scripts/ThirdParty/NativeCollection/Stack.cs
  26. 11 0
      Unity/Assets/Scripts/ThirdParty/NativeCollection/Stack.cs.meta
  27. 84 0
      Unity/Assets/Scripts/ThirdParty/NativeCollection/ThrowHelper.cs
  28. 11 0
      Unity/Assets/Scripts/ThirdParty/NativeCollection/ThrowHelper.cs.meta
  29. 8 0
      Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType.meta
  30. 76 0
      Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/Dictionary.cs
  31. 11 0
      Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/Dictionary.cs.meta
  32. 133 0
      Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/HashHelpers.cs
  33. 11 0
      Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/HashHelpers.cs.meta
  34. 476 0
      Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/HashSet.cs
  35. 11 0
      Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/HashSet.cs.meta
  36. 363 0
      Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/List.cs
  37. 11 0
      Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/List.cs.meta
  38. 8 0
      Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/MultiMap.meta
  39. 125 0
      Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/MultiMap/MultiMap.cs
  40. 11 0
      Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/MultiMap/MultiMap.cs.meta
  41. 62 0
      Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/MultiMap/MultiMapPair.cs
  42. 11 0
      Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/MultiMap/MultiMapPair.cs.meta
  43. 70 0
      Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/NativePool.cs
  44. 11 0
      Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/NativePool.cs.meta
  45. 163 0
      Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/Queue.cs
  46. 11 0
      Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/Queue.cs.meta
  47. 8 0
      Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/SortedSet.meta
  48. 355 0
      Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/SortedSet/Node.cs
  49. 11 0
      Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/SortedSet/Node.cs.meta
  50. 703 0
      Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/SortedSet/SortedSet.cs
  51. 11 0
      Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/SortedSet/SortedSet.cs.meta
  52. 121 0
      Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/Stack.cs
  53. 11 0
      Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/Stack.cs.meta
  54. 3 3
      Unity/Packages/manifest.json
  55. 11 11
      Unity/Packages/packages-lock.json
  56. 2 2
      Unity/ProjectSettings/ProjectVersion.txt

+ 4 - 0
DotNet/ThirdParty/DotNet.ThirdParty.csproj

@@ -42,6 +42,10 @@
       <Link>Kcp/%(RecursiveDir)%(FileName)%(Extension)</Link>
     </Compile>
 
+    <Compile Include="..\..\Unity\Assets\Scripts\ThirdParty\NativeCollection\**\*.cs">
+        <Link>NativeCollection/%(RecursiveDir)%(FileName)%(Extension)</Link>
+    </Compile>
+
     <Compile Include="..\..\Unity\Assets\Scripts\ThirdParty\Recast\Recast.cs">
       <Link>Recast\Recast.cs</Link>
     </Compile>

+ 2 - 2
Unity/Assets/Scripts/Core/Fiber/Module/Timer/TimerComponent.cs

@@ -77,7 +77,7 @@ namespace ET
             {
                 long time = self.timeOutTime.Dequeue();
                 var list = self.timeId[time];
-                for (int i = 0; i < list.Count; ++i)
+                for (int i = 0; i < list.Length; ++i)
                 {
                     long timerId = list[i];
                     self.timeOutTimerIds.Enqueue(timerId);
@@ -305,7 +305,7 @@ namespace ET
         /// <summary>
         /// key: time, value: timer id
         /// </summary>
-        public readonly MultiMap<long, long> timeId = new(1000);
+        public readonly NativeCollection.MultiMap<long, long> timeId = new(1000);
 
         public readonly Queue<long> timeOutTime = new();
 

+ 1 - 1
Unity/Assets/Scripts/Core/MultiMap.cs

@@ -3,7 +3,7 @@ using System.Collections.Generic;
 
 namespace ET
 {
-    public class MultiMap<T, K>: SortedCollection<T, List<K>>
+    public class MultiMap<T, K>: SortedDictionary<T, List<K>>
     {
         private readonly List<K> Empty = new();
         private readonly int maxPoolCount;

+ 2 - 2
Unity/Assets/Scripts/Core/Network/KService.cs

@@ -96,7 +96,7 @@ namespace ET
         // 下帧要更新的channel
         private readonly HashSet<long> updateIds = new HashSet<long>();
         // 下次时间更新的channel
-        private readonly MultiMap<long, long> timeId = new();
+        private readonly NativeCollection.MultiMap<long, long> timeId = new();
         private readonly List<long> timeOutTime = new List<long>();
         // 记录最小时间,不用每次都去MultiMap取第一个值
         private long minTime;
@@ -578,7 +578,7 @@ namespace ET
 
             this.timeOutTime.Clear();
 
-            foreach (KeyValuePair<long, List<long>> kv in this.timeId)
+            foreach (var kv in this.timeId)
             {
                 long k = kv.Key;
                 if (k > timeNow)

+ 0 - 248
Unity/Assets/Scripts/Core/SortedCollection.cs

@@ -1,248 +0,0 @@
-using System.Collections;
-using System.Collections.Generic;
-
-namespace ET
-{
-#if DOTNET
-    public class SortedCollection<K, V>: SortedDictionary<K, V>
-    {
-    }
-    
-#else
-    public class SortedCollection<K, V>: IEnumerable<KeyValuePair<K, V>>
-    {
-        private class Enumerator: IEnumerator<KeyValuePair<K, V>>
-        {
-            private readonly SortedCollection<K, V> sortedCollection;
-            private Node current;
-            private int index;
-
-            public Enumerator(SortedCollection<K, V> sortedCollection)
-            {
-                this.sortedCollection = sortedCollection;
-                this.index = 0;
-                this.current = null;
-            }
-            
-            public void Dispose()
-            {
-                // TODO release managed resources here
-            }
-
-            public bool MoveNext()
-            {
-                if (++this.index > this.sortedCollection.dict.Count)
-                {
-                    return false;
-                }
-                if (this.current == null)
-                {
-                    this.current = this.sortedCollection.head;
-                    return true;
-                }
-                if (this.current.Next == null)
-                {
-                    return false;
-                }
-                this.current = this.current.Next;
-                return true;
-            }
-
-            public void Reset()
-            {
-                this.index = 0;
-                this.current = null;
-            }
-
-            public KeyValuePair<K, V> Current
-            {
-                get
-                {
-                    return new KeyValuePair<K, V>(this.current.Key, this.current.Value);
-                }
-            }
-
-            object IEnumerator.Current => this.Current;
-        }
-        
-        public class Node
-        {
-            internal Node Next;
-            internal Node Pre;
-            public K Key;
-            public V Value;
-        }
-
-        private readonly IComparer<K> comparer;
-
-        private readonly Dictionary<K, Node> dict = new();
-        
-        private readonly Queue<Node> pool = new();
-
-        private Node head;
-
-        private readonly Enumerator enumerator;
-
-        public SortedCollection()
-        {
-            this.comparer = Comparer<K>.Default;
-            this.enumerator = new Enumerator(this);
-        }
-        
-        public SortedCollection(IComparer<K> comparer)
-        {
-            this.comparer = comparer ?? Comparer<K>.Default;
-            this.enumerator = new Enumerator(this);
-        }
-
-        private Node Fetch()
-        {
-            if (this.pool.Count == 0)
-            {
-                return new Node();
-            }
-            return this.pool.Dequeue();
-        }
-        
-        private void Recycle(Node node)
-        {
-            node.Next = null;
-            node.Pre = null;
-            node.Key = default;
-            node.Value = default;
-            if (this.pool.Count > 1000)
-            {
-                return;
-            }
-            this.pool.Enqueue(node);
-        }
-
-        public IEnumerator<KeyValuePair<K, V>> GetEnumerator()
-        {
-            this.enumerator.Reset();
-            return this.enumerator;
-        }
-
-        public void Add(K k, V v)
-        {
-            Node node = this.Fetch();
-            node.Key = k;
-            node.Value = v;
-            this.dict.Add(k, node);
-            
-            if (this.head == null)
-            {
-                this.head = node;
-                return;
-            }
-            
-            Node p = this.head;
-            if (comparer.Compare(k, p.Key) < 0)
-            {
-                node.Next = p;
-                p.Pre = node;
-                this.head = node;
-                return;
-            }
-
-            Node q = p.Next;
-            while (true)
-            {
-                if (q == null) // 到末尾
-                {
-                    p.Next = node;
-                    node.Pre = p;
-                    break;
-                }
-                
-                int ret = comparer.Compare(k, q.Key);
-
-                if (ret == 0)
-                {
-                    break;
-                }
-                
-                if (ret < 0)
-                {
-                    node.Next = q;
-                    q.Pre = node;
-                    p.Next = node;
-                    node.Pre = p;
-                    break;
-                }
-                
-                p = p.Next;
-                q = q.Next;
-            }
-        }
-
-        public bool Remove(K k)
-        {
-            if (!this.dict.Remove(k, out Node node))
-            {
-                return false;
-            }
-
-            if (this.dict.Count == 0)
-            {
-                this.head = null;
-                this.Recycle(node);
-                return true;
-            }
-
-            if (node.Pre == null)
-            {
-                node.Next.Pre = null;
-                this.head = node.Next;
-                this.Recycle(node);
-                return true;
-            }
-
-            if (node.Next == null)
-            {
-                node.Pre.Next = null;
-                this.Recycle(node);
-                return true;
-            }
-
-            node.Pre.Next = node.Next;
-            node.Next.Pre = node.Pre;
-            this.Recycle(node);
-            return true;
-        }
-
-        IEnumerator IEnumerable.GetEnumerator()
-        {
-            return this.GetEnumerator();
-        }
-
-        public V this[K k]
-        {
-            get
-            {
-                return this.dict[k].Value;
-            }
-            set
-            {
-                this.Remove(k);
-                this.Add(k, value);
-            }
-        }
-
-        public bool TryGetValue(K k, out V v)
-        {
-            bool ret = this.dict.TryGetValue(k, out Node node);
-            v = ret? node.Value : default;
-            return ret;
-        }
-
-        public int Count
-        {
-            get
-            {
-                return this.dict.Count;
-            }
-        }
-    }
-#endif
-}

+ 33 - 196
Unity/Assets/Scripts/Loader/Plugins/HybridCLR/Generated/AOTGenericReferences.cs

@@ -37,8 +37,9 @@ public class AOTGenericReferences : UnityEngine.MonoBehaviour
 	// ET.AEvent<object,ET.NumbericChange>
 	// ET.AInvokeHandler<ET.FiberInit,object>
 	// ET.AInvokeHandler<ET.MailBoxInvoker>
+	// ET.AInvokeHandler<ET.NetOuterComponentOnRead>
 	// ET.ATimer<object>
-	// ET.AwakeSystem<object,System.Net.Sockets.AddressFamily,int>
+	// ET.AwakeSystem<object,System.Net.Sockets.AddressFamily>
 	// ET.AwakeSystem<object,int>
 	// ET.AwakeSystem<object,object,int>
 	// ET.AwakeSystem<object,object,object>
@@ -67,7 +68,7 @@ public class AOTGenericReferences : UnityEngine.MonoBehaviour
 	// ET.ETTask<object>
 	// ET.ETTask<uint>
 	// ET.EntityRef<object>
-	// ET.IAwake<System.Net.Sockets.AddressFamily,int>
+	// ET.IAwake<System.Net.Sockets.AddressFamily>
 	// ET.IAwake<int>
 	// ET.IAwake<object,int>
 	// ET.IAwake<object,object>
@@ -92,6 +93,7 @@ public class AOTGenericReferences : UnityEngine.MonoBehaviour
 	// MemoryPack.MemoryPackFormatter<object>
 	// System.Action<long,ET.ActorId,object>
 	// System.Action<long,int>
+	// System.Action<long,object>
 	// System.Collections.Generic.Dictionary.Enumerator<int,long>
 	// System.Collections.Generic.Dictionary.Enumerator<int,object>
 	// System.Collections.Generic.Dictionary.Enumerator<long,ET.LSInput>
@@ -131,9 +133,7 @@ public class AOTGenericReferences : UnityEngine.MonoBehaviour
 	// System.Func<System.Collections.Generic.KeyValuePair<object,int>,int>
 	// System.Func<System.Collections.Generic.KeyValuePair<object,int>,object>
 	// System.Func<object>
-	// System.Runtime.CompilerServices.TaskAwaiter<int>
 	// System.Runtime.CompilerServices.TaskAwaiter<object>
-	// System.Threading.Tasks.Task<int>
 	// System.Threading.Tasks.Task<object>
 	// System.ValueTuple<uint,object>
 	// System.ValueTuple<uint,uint>
@@ -141,203 +141,38 @@ public class AOTGenericReferences : UnityEngine.MonoBehaviour
 
 	public void RefMethods()
 	{
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<ET.ETTaskCompleted,ET.Client.A2NetClient_MessageHandler.<Run>d__0>(ET.ETTaskCompleted&,ET.Client.A2NetClient_MessageHandler.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<ET.ETTaskCompleted,ET.Client.AfterCreateClientScene_AddComponent.<Run>d__0>(ET.ETTaskCompleted&,ET.Client.AfterCreateClientScene_AddComponent.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<ET.ETTaskCompleted,ET.Client.AfterCreateClientScene_LSAddComponent.<Run>d__0>(ET.ETTaskCompleted&,ET.Client.AfterCreateClientScene_LSAddComponent.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<ET.ETTaskCompleted,ET.Client.AfterCreateCurrentScene_AddComponent.<Run>d__0>(ET.ETTaskCompleted&,ET.Client.AfterCreateCurrentScene_AddComponent.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<ET.ETTaskCompleted,ET.Client.AfterUnitCreate_CreateUnitView.<Run>d__0>(ET.ETTaskCompleted&,ET.Client.AfterUnitCreate_CreateUnitView.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<ET.ETTaskCompleted,ET.Client.ChangePosition_SyncGameObjectPos.<Run>d__0>(ET.ETTaskCompleted&,ET.Client.ChangePosition_SyncGameObjectPos.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<ET.ETTaskCompleted,ET.Client.ChangeRotation_SyncGameObjectRotation.<Run>d__0>(ET.ETTaskCompleted&,ET.Client.ChangeRotation_SyncGameObjectRotation.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<ET.ETTaskCompleted,ET.Client.FiberInit_NetClient.<Handle>d__0>(ET.ETTaskCompleted&,ET.Client.FiberInit_NetClient.<Handle>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<ET.ETTaskCompleted,ET.Client.G2C_ReconnectHandler.<Run>d__0>(ET.ETTaskCompleted&,ET.Client.G2C_ReconnectHandler.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<ET.ETTaskCompleted,ET.Client.LSSceneInitFinish_Finish.<Run>d__0>(ET.ETTaskCompleted&,ET.Client.LSSceneInitFinish_Finish.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<ET.ETTaskCompleted,ET.Client.M2C_CreateMyUnitHandler.<Run>d__0>(ET.ETTaskCompleted&,ET.Client.M2C_CreateMyUnitHandler.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<ET.ETTaskCompleted,ET.Client.M2C_CreateUnitsHandler.<Run>d__0>(ET.ETTaskCompleted&,ET.Client.M2C_CreateUnitsHandler.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<ET.ETTaskCompleted,ET.Client.M2C_RemoveUnitsHandler.<Run>d__0>(ET.ETTaskCompleted&,ET.Client.M2C_RemoveUnitsHandler.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<ET.ETTaskCompleted,ET.Client.M2C_StopHandler.<Run>d__0>(ET.ETTaskCompleted&,ET.Client.M2C_StopHandler.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<ET.ETTaskCompleted,ET.Client.NetClient2Main_SessionDisposeHandler.<Run>d__0>(ET.ETTaskCompleted&,ET.Client.NetClient2Main_SessionDisposeHandler.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<ET.ETTaskCompleted,ET.Client.OneFrameInputsHandler.<Run>d__0>(ET.ETTaskCompleted&,ET.Client.OneFrameInputsHandler.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<ET.ETTaskCompleted,ET.Client.Room2C_AdjustUpdateTimeHandler.<Run>d__0>(ET.ETTaskCompleted&,ET.Client.Room2C_AdjustUpdateTimeHandler.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<ET.ETTaskCompleted,ET.Client.Room2C_CheckHashFailHandler.<Run>d__0>(ET.ETTaskCompleted&,ET.Client.Room2C_CheckHashFailHandler.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<ET.ETTaskCompleted,ET.Client.Room2C_EnterMapHandler.<Run>d__0>(ET.ETTaskCompleted&,ET.Client.Room2C_EnterMapHandler.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<ET.ETTaskCompleted,ET.Client.UIHelper.<Remove>d__1>(ET.ETTaskCompleted&,ET.Client.UIHelper.<Remove>d__1&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<ET.ETTaskCompleted,ET.EntryEvent1_InitShare.<Run>d__0>(ET.ETTaskCompleted&,ET.EntryEvent1_InitShare.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<ET.ETTaskCompleted,ET.NumericChangeEvent_NotifyWatcher.<Run>d__0>(ET.ETTaskCompleted&,ET.NumericChangeEvent_NotifyWatcher.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<ET.ETTaskCompleted,ET.ReloadConfigConsoleHandler.<Run>d__0>(ET.ETTaskCompleted&,ET.ReloadConfigConsoleHandler.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<ET.ETTaskCompleted,ET.ReloadDllConsoleHandler.<Run>d__0>(ET.ETTaskCompleted&,ET.ReloadDllConsoleHandler.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<System.Runtime.CompilerServices.TaskAwaiter,ET.Client.ClientSenderCompnentSystem.<RemoveFiberAsync>d__2>(System.Runtime.CompilerServices.TaskAwaiter&,ET.Client.ClientSenderCompnentSystem.<RemoveFiberAsync>d__2&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<System.Runtime.CompilerServices.TaskAwaiter<int>,ET.Entry.<StartAsync>d__2>(System.Runtime.CompilerServices.TaskAwaiter<int>&,ET.Entry.<StartAsync>d__2&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<System.Runtime.CompilerServices.TaskAwaiter<object>,ET.ConsoleComponentSystem.<Start>d__1>(System.Runtime.CompilerServices.TaskAwaiter<object>&,ET.ConsoleComponentSystem.<Start>d__1&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<object,ET.Client.A2NetClient_RequestHandler.<Run>d__0>(object&,ET.Client.A2NetClient_RequestHandler.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<object,ET.Client.AI_Attack.<Execute>d__1>(object&,ET.Client.AI_Attack.<Execute>d__1&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<object,ET.Client.AI_XunLuo.<Execute>d__1>(object&,ET.Client.AI_XunLuo.<Execute>d__1&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<object,ET.Client.AppStartInitFinish_CreateLoginUI.<Run>d__0>(object&,ET.Client.AppStartInitFinish_CreateLoginUI.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<object,ET.Client.AppStartInitFinish_CreateUILSLogin.<Run>d__0>(object&,ET.Client.AppStartInitFinish_CreateUILSLogin.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<object,ET.Client.EnterMapHelper.<EnterMapAsync>d__0>(object&,ET.Client.EnterMapHelper.<EnterMapAsync>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<object,ET.Client.EnterMapHelper.<Match>d__1>(object&,ET.Client.EnterMapHelper.<Match>d__1&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<object,ET.Client.EntryEvent3_InitClient.<Run>d__0>(object&,ET.Client.EntryEvent3_InitClient.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<object,ET.Client.G2C_ReconnectHandler.<Run>d__0>(object&,ET.Client.G2C_ReconnectHandler.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<object,ET.Client.LSSceneChangeHelper.<SceneChangeTo>d__0>(object&,ET.Client.LSSceneChangeHelper.<SceneChangeTo>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<object,ET.Client.LSSceneChangeHelper.<SceneChangeToReconnect>d__2>(object&,ET.Client.LSSceneChangeHelper.<SceneChangeToReconnect>d__2&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<object,ET.Client.LSSceneChangeHelper.<SceneChangeToReplay>d__1>(object&,ET.Client.LSSceneChangeHelper.<SceneChangeToReplay>d__1&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<object,ET.Client.LSSceneChangeStart_AddComponent.<Run>d__0>(object&,ET.Client.LSSceneChangeStart_AddComponent.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<object,ET.Client.LSSceneInitFinish_Finish.<Run>d__0>(object&,ET.Client.LSSceneInitFinish_Finish.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<object,ET.Client.LoginFinish_CreateLobbyUI.<Run>d__0>(object&,ET.Client.LoginFinish_CreateLobbyUI.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<object,ET.Client.LoginFinish_CreateUILSLobby.<Run>d__0>(object&,ET.Client.LoginFinish_CreateUILSLobby.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<object,ET.Client.LoginFinish_RemoveLoginUI.<Run>d__0>(object&,ET.Client.LoginFinish_RemoveLoginUI.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<object,ET.Client.LoginFinish_RemoveUILSLogin.<Run>d__0>(object&,ET.Client.LoginFinish_RemoveUILSLogin.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<object,ET.Client.LoginHelper.<Login>d__0>(object&,ET.Client.LoginHelper.<Login>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<object,ET.Client.M2C_PathfindingResultHandler.<Run>d__0>(object&,ET.Client.M2C_PathfindingResultHandler.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<object,ET.Client.M2C_StartSceneChangeHandler.<Run>d__0>(object&,ET.Client.M2C_StartSceneChangeHandler.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<object,ET.Client.Main2NetClient_LoginHandler.<Run>d__0>(object&,ET.Client.Main2NetClient_LoginHandler.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<object,ET.Client.Match2G_NotifyMatchSuccessHandler.<Run>d__0>(object&,ET.Client.Match2G_NotifyMatchSuccessHandler.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<object,ET.Client.MoveHelper.<MoveToAsync>d__1>(object&,ET.Client.MoveHelper.<MoveToAsync>d__1&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<object,ET.Client.PingComponentSystem.<PingAsync>d__2>(object&,ET.Client.PingComponentSystem.<PingAsync>d__2&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<object,ET.Client.ResourcesComponentSystem.<>c__DisplayClass13_0.<<LoadBundleAsync>g__LoadDependency|0>d>(object&,ET.Client.ResourcesComponentSystem.<>c__DisplayClass13_0.<<LoadBundleAsync>g__LoadDependency|0>d&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<object,ET.Client.ResourcesComponentSystem.<LoadBundleAsync>d__13>(object&,ET.Client.ResourcesComponentSystem.<LoadBundleAsync>d__13&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<object,ET.Client.ResourcesComponentSystem.<LoadOneBundleAllAssets>d__15>(object&,ET.Client.ResourcesComponentSystem.<LoadOneBundleAllAssets>d__15&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<object,ET.Client.ResourcesComponentSystem.<UnloadBundleAsync>d__7>(object&,ET.Client.ResourcesComponentSystem.<UnloadBundleAsync>d__7&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<object,ET.Client.ResourcesLoaderComponentSystem.<>c__DisplayClass0_0.<<Destroy>g__UnLoadAsync|0>d>(object&,ET.Client.ResourcesLoaderComponentSystem.<>c__DisplayClass0_0.<<Destroy>g__UnLoadAsync|0>d&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<object,ET.Client.ResourcesLoaderComponentSystem.<LoadAsync>d__1>(object&,ET.Client.ResourcesLoaderComponentSystem.<LoadAsync>d__1&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<object,ET.Client.RouterAddressComponentSystem.<GetAllRouter>d__2>(object&,ET.Client.RouterAddressComponentSystem.<GetAllRouter>d__2&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<object,ET.Client.RouterAddressComponentSystem.<Init>d__1>(object&,ET.Client.RouterAddressComponentSystem.<Init>d__1&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<object,ET.Client.RouterAddressComponentSystem.<WaitTenMinGetAllRouter>d__3>(object&,ET.Client.RouterAddressComponentSystem.<WaitTenMinGetAllRouter>d__3&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<object,ET.Client.RouterCheckComponentSystem.<CheckAsync>d__1>(object&,ET.Client.RouterCheckComponentSystem.<CheckAsync>d__1&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<object,ET.Client.SceneChangeFinishEvent_CreateUIHelp.<Run>d__0>(object&,ET.Client.SceneChangeFinishEvent_CreateUIHelp.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<object,ET.Client.SceneChangeHelper.<SceneChangeTo>d__0>(object&,ET.Client.SceneChangeHelper.<SceneChangeTo>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<object,ET.Client.SceneChangeStart_AddComponent.<Run>d__0>(object&,ET.Client.SceneChangeStart_AddComponent.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<object,ET.Client.UILSLobbyComponentSystem.<EnterMap>d__1>(object&,ET.Client.UILSLobbyComponentSystem.<EnterMap>d__1&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<object,ET.Client.UILobbyComponentSystem.<EnterMap>d__1>(object&,ET.Client.UILobbyComponentSystem.<EnterMap>d__1&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<object,ET.ConsoleComponentSystem.<Start>d__1>(object&,ET.ConsoleComponentSystem.<Start>d__1&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<object,ET.EntryEvent1_InitShare.<Run>d__0>(object&,ET.EntryEvent1_InitShare.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<object,ET.FiberInit_Main.<Handle>d__0>(object&,ET.FiberInit_Main.<Handle>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<object,ET.MailBoxType_OrderedMessageHandler.<HandleInner>d__1>(object&,ET.MailBoxType_OrderedMessageHandler.<HandleInner>d__1&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<object,ET.MailBoxType_UnOrderedMessageHandler.<HandleAsync>d__1>(object&,ET.MailBoxType_UnOrderedMessageHandler.<HandleAsync>d__1&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<object,ET.SessionSystem.<>c__DisplayClass4_0.<<Call>g__Timeout|0>d>(object&,ET.SessionSystem.<>c__DisplayClass4_0.<<Call>g__Timeout|0>d&)
-		// System.Void ET.ETAsyncTaskMethodBuilder<System.ValueTuple<uint,object>>.AwaitUnsafeOnCompleted<object,ET.Client.RouterHelper.<GetRouterAddress>d__1>(object&,ET.Client.RouterHelper.<GetRouterAddress>d__1&)
-		// System.Void ET.ETAsyncTaskMethodBuilder<byte>.AwaitUnsafeOnCompleted<object,ET.MoveComponentSystem.<MoveToAsync>d__5>(object&,ET.MoveComponentSystem.<MoveToAsync>d__5&)
-		// System.Void ET.ETAsyncTaskMethodBuilder<int>.AwaitUnsafeOnCompleted<object,ET.Client.MoveHelper.<MoveToAsync>d__0>(object&,ET.Client.MoveHelper.<MoveToAsync>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder<long>.AwaitUnsafeOnCompleted<System.Runtime.CompilerServices.TaskAwaiter<int>,ET.Client.ClientSenderCompnentSystem.<LoginAsync>d__3>(System.Runtime.CompilerServices.TaskAwaiter<int>&,ET.Client.ClientSenderCompnentSystem.<LoginAsync>d__3&)
-		// System.Void ET.ETAsyncTaskMethodBuilder<long>.AwaitUnsafeOnCompleted<object,ET.Client.ClientSenderCompnentSystem.<LoginAsync>d__3>(object&,ET.Client.ClientSenderCompnentSystem.<LoginAsync>d__3&)
-		// System.Void ET.ETAsyncTaskMethodBuilder<object>.AwaitUnsafeOnCompleted<ET.ETTaskCompleted,ET.Client.UILSLobbyEvent.<OnCreate>d__0>(ET.ETTaskCompleted&,ET.Client.UILSLobbyEvent.<OnCreate>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder<object>.AwaitUnsafeOnCompleted<ET.ETTaskCompleted,ET.Client.UILobbyEvent.<OnCreate>d__0>(ET.ETTaskCompleted&,ET.Client.UILobbyEvent.<OnCreate>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder<object>.AwaitUnsafeOnCompleted<System.Runtime.CompilerServices.TaskAwaiter<object>,ET.Client.HttpClientHelper.<Get>d__0>(System.Runtime.CompilerServices.TaskAwaiter<object>&,ET.Client.HttpClientHelper.<Get>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder<object>.AwaitUnsafeOnCompleted<object,ET.Client.ClientSenderCompnentSystem.<Call>d__5>(object&,ET.Client.ClientSenderCompnentSystem.<Call>d__5&)
-		// System.Void ET.ETAsyncTaskMethodBuilder<object>.AwaitUnsafeOnCompleted<object,ET.Client.ResourcesComponentSystem.<LoadOneBundleAsync>d__14>(object&,ET.Client.ResourcesComponentSystem.<LoadOneBundleAsync>d__14&)
-		// System.Void ET.ETAsyncTaskMethodBuilder<object>.AwaitUnsafeOnCompleted<object,ET.Client.RouterHelper.<CreateRouterSession>d__0>(object&,ET.Client.RouterHelper.<CreateRouterSession>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder<object>.AwaitUnsafeOnCompleted<object,ET.Client.UIComponentSystem.<Create>d__1>(object&,ET.Client.UIComponentSystem.<Create>d__1&)
-		// System.Void ET.ETAsyncTaskMethodBuilder<object>.AwaitUnsafeOnCompleted<object,ET.Client.UIGlobalComponentSystem.<OnCreate>d__1>(object&,ET.Client.UIGlobalComponentSystem.<OnCreate>d__1&)
-		// System.Void ET.ETAsyncTaskMethodBuilder<object>.AwaitUnsafeOnCompleted<object,ET.Client.UIHelpEvent.<OnCreate>d__0>(object&,ET.Client.UIHelpEvent.<OnCreate>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder<object>.AwaitUnsafeOnCompleted<object,ET.Client.UIHelper.<Create>d__0>(object&,ET.Client.UIHelper.<Create>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder<object>.AwaitUnsafeOnCompleted<object,ET.Client.UILSLobbyEvent.<OnCreate>d__0>(object&,ET.Client.UILSLobbyEvent.<OnCreate>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder<object>.AwaitUnsafeOnCompleted<object,ET.Client.UILSLoginEvent.<OnCreate>d__0>(object&,ET.Client.UILSLoginEvent.<OnCreate>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder<object>.AwaitUnsafeOnCompleted<object,ET.Client.UILSRoomEvent.<OnCreate>d__0>(object&,ET.Client.UILSRoomEvent.<OnCreate>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder<object>.AwaitUnsafeOnCompleted<object,ET.Client.UILobbyEvent.<OnCreate>d__0>(object&,ET.Client.UILobbyEvent.<OnCreate>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder<object>.AwaitUnsafeOnCompleted<object,ET.Client.UILoginEvent.<OnCreate>d__0>(object&,ET.Client.UILoginEvent.<OnCreate>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder<object>.AwaitUnsafeOnCompleted<object,ET.SessionSystem.<Call>d__3>(object&,ET.SessionSystem.<Call>d__3&)
-		// System.Void ET.ETAsyncTaskMethodBuilder<object>.AwaitUnsafeOnCompleted<object,ET.SessionSystem.<Call>d__4>(object&,ET.SessionSystem.<Call>d__4&)
-		// System.Void ET.ETAsyncTaskMethodBuilder<uint>.AwaitUnsafeOnCompleted<object,ET.Client.RouterHelper.<Connect>d__2>(object&,ET.Client.RouterHelper.<Connect>d__2&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.A2NetClient_MessageHandler.<Run>d__0>(ET.Client.A2NetClient_MessageHandler.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.A2NetClient_RequestHandler.<Run>d__0>(ET.Client.A2NetClient_RequestHandler.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.AI_Attack.<Execute>d__1>(ET.Client.AI_Attack.<Execute>d__1&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.AI_XunLuo.<Execute>d__1>(ET.Client.AI_XunLuo.<Execute>d__1&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.AfterCreateClientScene_AddComponent.<Run>d__0>(ET.Client.AfterCreateClientScene_AddComponent.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.AfterCreateClientScene_LSAddComponent.<Run>d__0>(ET.Client.AfterCreateClientScene_LSAddComponent.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.AfterCreateCurrentScene_AddComponent.<Run>d__0>(ET.Client.AfterCreateCurrentScene_AddComponent.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.AfterUnitCreate_CreateUnitView.<Run>d__0>(ET.Client.AfterUnitCreate_CreateUnitView.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.AppStartInitFinish_CreateLoginUI.<Run>d__0>(ET.Client.AppStartInitFinish_CreateLoginUI.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.AppStartInitFinish_CreateUILSLogin.<Run>d__0>(ET.Client.AppStartInitFinish_CreateUILSLogin.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.ChangePosition_SyncGameObjectPos.<Run>d__0>(ET.Client.ChangePosition_SyncGameObjectPos.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.ChangeRotation_SyncGameObjectRotation.<Run>d__0>(ET.Client.ChangeRotation_SyncGameObjectRotation.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.ClientSenderCompnentSystem.<RemoveFiberAsync>d__2>(ET.Client.ClientSenderCompnentSystem.<RemoveFiberAsync>d__2&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.EnterMapHelper.<EnterMapAsync>d__0>(ET.Client.EnterMapHelper.<EnterMapAsync>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.EnterMapHelper.<Match>d__1>(ET.Client.EnterMapHelper.<Match>d__1&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.EntryEvent3_InitClient.<Run>d__0>(ET.Client.EntryEvent3_InitClient.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.FiberInit_NetClient.<Handle>d__0>(ET.Client.FiberInit_NetClient.<Handle>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.G2C_ReconnectHandler.<Run>d__0>(ET.Client.G2C_ReconnectHandler.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.LSSceneChangeHelper.<SceneChangeTo>d__0>(ET.Client.LSSceneChangeHelper.<SceneChangeTo>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.LSSceneChangeHelper.<SceneChangeToReconnect>d__2>(ET.Client.LSSceneChangeHelper.<SceneChangeToReconnect>d__2&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.LSSceneChangeHelper.<SceneChangeToReplay>d__1>(ET.Client.LSSceneChangeHelper.<SceneChangeToReplay>d__1&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.LSSceneChangeStart_AddComponent.<Run>d__0>(ET.Client.LSSceneChangeStart_AddComponent.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.LSSceneInitFinish_Finish.<Run>d__0>(ET.Client.LSSceneInitFinish_Finish.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.LoginFinish_CreateLobbyUI.<Run>d__0>(ET.Client.LoginFinish_CreateLobbyUI.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.LoginFinish_CreateUILSLobby.<Run>d__0>(ET.Client.LoginFinish_CreateUILSLobby.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.LoginFinish_RemoveLoginUI.<Run>d__0>(ET.Client.LoginFinish_RemoveLoginUI.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.LoginFinish_RemoveUILSLogin.<Run>d__0>(ET.Client.LoginFinish_RemoveUILSLogin.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.LoginHelper.<Login>d__0>(ET.Client.LoginHelper.<Login>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.M2C_CreateMyUnitHandler.<Run>d__0>(ET.Client.M2C_CreateMyUnitHandler.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.M2C_CreateUnitsHandler.<Run>d__0>(ET.Client.M2C_CreateUnitsHandler.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.M2C_PathfindingResultHandler.<Run>d__0>(ET.Client.M2C_PathfindingResultHandler.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.M2C_RemoveUnitsHandler.<Run>d__0>(ET.Client.M2C_RemoveUnitsHandler.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.M2C_StartSceneChangeHandler.<Run>d__0>(ET.Client.M2C_StartSceneChangeHandler.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.M2C_StopHandler.<Run>d__0>(ET.Client.M2C_StopHandler.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.Main2NetClient_LoginHandler.<Run>d__0>(ET.Client.Main2NetClient_LoginHandler.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.Match2G_NotifyMatchSuccessHandler.<Run>d__0>(ET.Client.Match2G_NotifyMatchSuccessHandler.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.MoveHelper.<MoveToAsync>d__1>(ET.Client.MoveHelper.<MoveToAsync>d__1&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.NetClient2Main_SessionDisposeHandler.<Run>d__0>(ET.Client.NetClient2Main_SessionDisposeHandler.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.OneFrameInputsHandler.<Run>d__0>(ET.Client.OneFrameInputsHandler.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.PingComponentSystem.<PingAsync>d__2>(ET.Client.PingComponentSystem.<PingAsync>d__2&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.ResourcesComponentSystem.<>c__DisplayClass13_0.<<LoadBundleAsync>g__LoadDependency|0>d>(ET.Client.ResourcesComponentSystem.<>c__DisplayClass13_0.<<LoadBundleAsync>g__LoadDependency|0>d&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.ResourcesComponentSystem.<LoadBundleAsync>d__13>(ET.Client.ResourcesComponentSystem.<LoadBundleAsync>d__13&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.ResourcesComponentSystem.<LoadOneBundleAllAssets>d__15>(ET.Client.ResourcesComponentSystem.<LoadOneBundleAllAssets>d__15&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.ResourcesComponentSystem.<UnloadBundleAsync>d__7>(ET.Client.ResourcesComponentSystem.<UnloadBundleAsync>d__7&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.ResourcesLoaderComponentSystem.<>c__DisplayClass0_0.<<Destroy>g__UnLoadAsync|0>d>(ET.Client.ResourcesLoaderComponentSystem.<>c__DisplayClass0_0.<<Destroy>g__UnLoadAsync|0>d&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.ResourcesLoaderComponentSystem.<LoadAsync>d__1>(ET.Client.ResourcesLoaderComponentSystem.<LoadAsync>d__1&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.Room2C_AdjustUpdateTimeHandler.<Run>d__0>(ET.Client.Room2C_AdjustUpdateTimeHandler.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.Room2C_CheckHashFailHandler.<Run>d__0>(ET.Client.Room2C_CheckHashFailHandler.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.Room2C_EnterMapHandler.<Run>d__0>(ET.Client.Room2C_EnterMapHandler.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.RouterAddressComponentSystem.<GetAllRouter>d__2>(ET.Client.RouterAddressComponentSystem.<GetAllRouter>d__2&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.RouterAddressComponentSystem.<Init>d__1>(ET.Client.RouterAddressComponentSystem.<Init>d__1&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.RouterAddressComponentSystem.<WaitTenMinGetAllRouter>d__3>(ET.Client.RouterAddressComponentSystem.<WaitTenMinGetAllRouter>d__3&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.RouterCheckComponentSystem.<CheckAsync>d__1>(ET.Client.RouterCheckComponentSystem.<CheckAsync>d__1&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.SceneChangeFinishEvent_CreateUIHelp.<Run>d__0>(ET.Client.SceneChangeFinishEvent_CreateUIHelp.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.SceneChangeHelper.<SceneChangeTo>d__0>(ET.Client.SceneChangeHelper.<SceneChangeTo>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.SceneChangeStart_AddComponent.<Run>d__0>(ET.Client.SceneChangeStart_AddComponent.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.UIHelper.<Remove>d__1>(ET.Client.UIHelper.<Remove>d__1&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.UILSLobbyComponentSystem.<EnterMap>d__1>(ET.Client.UILSLobbyComponentSystem.<EnterMap>d__1&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Client.UILobbyComponentSystem.<EnterMap>d__1>(ET.Client.UILobbyComponentSystem.<EnterMap>d__1&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.ConsoleComponentSystem.<Start>d__1>(ET.ConsoleComponentSystem.<Start>d__1&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.Entry.<StartAsync>d__2>(ET.Entry.<StartAsync>d__2&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.EntryEvent1_InitShare.<Run>d__0>(ET.EntryEvent1_InitShare.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.FiberInit_Main.<Handle>d__0>(ET.FiberInit_Main.<Handle>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.MailBoxType_OrderedMessageHandler.<HandleInner>d__1>(ET.MailBoxType_OrderedMessageHandler.<HandleInner>d__1&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.MailBoxType_UnOrderedMessageHandler.<HandleAsync>d__1>(ET.MailBoxType_UnOrderedMessageHandler.<HandleAsync>d__1&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.MessageHandler.<Handle>d__1<object,object,object>>(ET.MessageHandler.<Handle>d__1<object,object,object>&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.MessageHandler.<Handle>d__1<object,object>>(ET.MessageHandler.<Handle>d__1<object,object>&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.NumericChangeEvent_NotifyWatcher.<Run>d__0>(ET.NumericChangeEvent_NotifyWatcher.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.ReloadConfigConsoleHandler.<Run>d__0>(ET.ReloadConfigConsoleHandler.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.ReloadDllConsoleHandler.<Run>d__0>(ET.ReloadDllConsoleHandler.<Run>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder.Start<ET.SessionSystem.<>c__DisplayClass4_0.<<Call>g__Timeout|0>d>(ET.SessionSystem.<>c__DisplayClass4_0.<<Call>g__Timeout|0>d&)
-		// System.Void ET.ETAsyncTaskMethodBuilder<ET.Client.WaitType.Wait_Room2C_Start>.Start<ET.ObjectWaitSystem.<Wait>d__4<ET.Client.WaitType.Wait_Room2C_Start>>(ET.ObjectWaitSystem.<Wait>d__4<ET.Client.WaitType.Wait_Room2C_Start>&)
-		// System.Void ET.ETAsyncTaskMethodBuilder<ET.Client.Wait_CreateMyUnit>.Start<ET.ObjectWaitSystem.<Wait>d__4<ET.Client.Wait_CreateMyUnit>>(ET.ObjectWaitSystem.<Wait>d__4<ET.Client.Wait_CreateMyUnit>&)
-		// System.Void ET.ETAsyncTaskMethodBuilder<ET.Client.Wait_SceneChangeFinish>.Start<ET.ObjectWaitSystem.<Wait>d__4<ET.Client.Wait_SceneChangeFinish>>(ET.ObjectWaitSystem.<Wait>d__4<ET.Client.Wait_SceneChangeFinish>&)
-		// System.Void ET.ETAsyncTaskMethodBuilder<ET.Client.Wait_UnitStop>.Start<ET.ObjectWaitSystem.<Wait>d__4<ET.Client.Wait_UnitStop>>(ET.ObjectWaitSystem.<Wait>d__4<ET.Client.Wait_UnitStop>&)
-		// System.Void ET.ETAsyncTaskMethodBuilder<System.ValueTuple<uint,object>>.Start<ET.Client.RouterHelper.<GetRouterAddress>d__1>(ET.Client.RouterHelper.<GetRouterAddress>d__1&)
-		// System.Void ET.ETAsyncTaskMethodBuilder<byte>.Start<ET.MoveComponentSystem.<MoveToAsync>d__5>(ET.MoveComponentSystem.<MoveToAsync>d__5&)
-		// System.Void ET.ETAsyncTaskMethodBuilder<int>.Start<ET.Client.MoveHelper.<MoveToAsync>d__0>(ET.Client.MoveHelper.<MoveToAsync>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder<long>.Start<ET.Client.ClientSenderCompnentSystem.<LoginAsync>d__3>(ET.Client.ClientSenderCompnentSystem.<LoginAsync>d__3&)
-		// System.Void ET.ETAsyncTaskMethodBuilder<object>.Start<ET.Client.ClientSenderCompnentSystem.<Call>d__5>(ET.Client.ClientSenderCompnentSystem.<Call>d__5&)
-		// System.Void ET.ETAsyncTaskMethodBuilder<object>.Start<ET.Client.HttpClientHelper.<Get>d__0>(ET.Client.HttpClientHelper.<Get>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder<object>.Start<ET.Client.ResourcesComponentSystem.<LoadOneBundleAsync>d__14>(ET.Client.ResourcesComponentSystem.<LoadOneBundleAsync>d__14&)
-		// System.Void ET.ETAsyncTaskMethodBuilder<object>.Start<ET.Client.RouterHelper.<CreateRouterSession>d__0>(ET.Client.RouterHelper.<CreateRouterSession>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder<object>.Start<ET.Client.UIComponentSystem.<Create>d__1>(ET.Client.UIComponentSystem.<Create>d__1&)
-		// System.Void ET.ETAsyncTaskMethodBuilder<object>.Start<ET.Client.UIGlobalComponentSystem.<OnCreate>d__1>(ET.Client.UIGlobalComponentSystem.<OnCreate>d__1&)
-		// System.Void ET.ETAsyncTaskMethodBuilder<object>.Start<ET.Client.UIHelpEvent.<OnCreate>d__0>(ET.Client.UIHelpEvent.<OnCreate>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder<object>.Start<ET.Client.UIHelper.<Create>d__0>(ET.Client.UIHelper.<Create>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder<object>.Start<ET.Client.UILSLobbyEvent.<OnCreate>d__0>(ET.Client.UILSLobbyEvent.<OnCreate>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder<object>.Start<ET.Client.UILSLoginEvent.<OnCreate>d__0>(ET.Client.UILSLoginEvent.<OnCreate>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder<object>.Start<ET.Client.UILSRoomEvent.<OnCreate>d__0>(ET.Client.UILSRoomEvent.<OnCreate>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder<object>.Start<ET.Client.UILobbyEvent.<OnCreate>d__0>(ET.Client.UILobbyEvent.<OnCreate>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder<object>.Start<ET.Client.UILoginEvent.<OnCreate>d__0>(ET.Client.UILoginEvent.<OnCreate>d__0&)
-		// System.Void ET.ETAsyncTaskMethodBuilder<object>.Start<ET.SessionSystem.<Call>d__3>(ET.SessionSystem.<Call>d__3&)
-		// System.Void ET.ETAsyncTaskMethodBuilder<object>.Start<ET.SessionSystem.<Call>d__4>(ET.SessionSystem.<Call>d__4&)
-		// System.Void ET.ETAsyncTaskMethodBuilder<uint>.Start<ET.Client.RouterHelper.<Connect>d__2>(ET.Client.RouterHelper.<Connect>d__2&)
+		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<ET.ETTaskCompleted,object>(ET.ETTaskCompleted&,object&)
+		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<System.Runtime.CompilerServices.TaskAwaiter<object>,object>(System.Runtime.CompilerServices.TaskAwaiter<object>&,object&)
+		// System.Void ET.ETAsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<object,object>(object&,object&)
+		// System.Void ET.ETAsyncTaskMethodBuilder<ET.Client.WaitType.Wait_Room2C_Start>.AwaitUnsafeOnCompleted<object,object>(object&,object&)
+		// System.Void ET.ETAsyncTaskMethodBuilder<ET.Client.Wait_CreateMyUnit>.AwaitUnsafeOnCompleted<object,object>(object&,object&)
+		// System.Void ET.ETAsyncTaskMethodBuilder<ET.Client.Wait_SceneChangeFinish>.AwaitUnsafeOnCompleted<object,object>(object&,object&)
+		// System.Void ET.ETAsyncTaskMethodBuilder<ET.Client.Wait_UnitStop>.AwaitUnsafeOnCompleted<object,object>(object&,object&)
+		// System.Void ET.ETAsyncTaskMethodBuilder<System.ValueTuple<uint,object>>.AwaitUnsafeOnCompleted<object,object>(object&,object&)
+		// System.Void ET.ETAsyncTaskMethodBuilder<byte>.AwaitUnsafeOnCompleted<object,object>(object&,object&)
+		// System.Void ET.ETAsyncTaskMethodBuilder<int>.AwaitUnsafeOnCompleted<object,object>(object&,object&)
+		// System.Void ET.ETAsyncTaskMethodBuilder<long>.AwaitUnsafeOnCompleted<object,object>(object&,object&)
+		// System.Void ET.ETAsyncTaskMethodBuilder<object>.AwaitUnsafeOnCompleted<ET.ETTaskCompleted,object>(ET.ETTaskCompleted&,object&)
+		// System.Void ET.ETAsyncTaskMethodBuilder<object>.AwaitUnsafeOnCompleted<System.Runtime.CompilerServices.TaskAwaiter<object>,object>(System.Runtime.CompilerServices.TaskAwaiter<object>&,object&)
+		// System.Void ET.ETAsyncTaskMethodBuilder<object>.AwaitUnsafeOnCompleted<object,object>(object&,object&)
+		// System.Void ET.ETAsyncTaskMethodBuilder<uint>.AwaitUnsafeOnCompleted<object,object>(object&,object&)
+		// System.Void ET.ETAsyncTaskMethodBuilder.Start<object>(object&)
+		// System.Void ET.ETAsyncTaskMethodBuilder<ET.Client.WaitType.Wait_Room2C_Start>.Start<object>(object&)
+		// System.Void ET.ETAsyncTaskMethodBuilder<ET.Client.Wait_CreateMyUnit>.Start<object>(object&)
+		// System.Void ET.ETAsyncTaskMethodBuilder<ET.Client.Wait_SceneChangeFinish>.Start<object>(object&)
+		// System.Void ET.ETAsyncTaskMethodBuilder<ET.Client.Wait_UnitStop>.Start<object>(object&)
+		// System.Void ET.ETAsyncTaskMethodBuilder<System.ValueTuple<uint,object>>.Start<object>(object&)
+		// System.Void ET.ETAsyncTaskMethodBuilder<byte>.Start<object>(object&)
+		// System.Void ET.ETAsyncTaskMethodBuilder<int>.Start<object>(object&)
+		// System.Void ET.ETAsyncTaskMethodBuilder<long>.Start<object>(object&)
+		// System.Void ET.ETAsyncTaskMethodBuilder<object>.Start<object>(object&)
+		// System.Void ET.ETAsyncTaskMethodBuilder<uint>.Start<object>(object&)
 		// object ET.Entity.AddChild<object,object,object>(object,object,bool)
 		// object ET.Entity.AddChildWithId<object,int>(long,int,bool)
 		// object ET.Entity.AddChildWithId<object,object>(long,object,bool)
 		// object ET.Entity.AddChildWithId<object>(long,bool)
 		// object ET.Entity.AddComponent<object,ET.MailBoxType>(ET.MailBoxType,bool)
-		// object ET.Entity.AddComponent<object,System.Net.Sockets.AddressFamily,int>(System.Net.Sockets.AddressFamily,int,bool)
+		// object ET.Entity.AddComponent<object,System.Net.Sockets.AddressFamily>(System.Net.Sockets.AddressFamily,bool)
 		// object ET.Entity.AddComponent<object,object,int>(object,int,bool)
 		// object ET.Entity.AddComponent<object>(bool)
 		// object ET.Entity.AddComponentWithId<object>(long,bool)
@@ -346,6 +181,7 @@ public class AOTGenericReferences : UnityEngine.MonoBehaviour
 		// object ET.Entity.GetParent<object>()
 		// System.Void ET.Entity.RemoveComponent<object>()
 		// ET.SceneType ET.EnumHelper.FromString<ET.SceneType>(string)
+		// System.Void ET.EventSystem.Invoke<ET.NetOuterComponentOnRead>(long,ET.NetOuterComponentOnRead)
 		// System.Void ET.EventSystem.Publish<object,ET.ChangePosition>(object,ET.ChangePosition)
 		// System.Void ET.EventSystem.Publish<object,ET.ChangeRotation>(object,ET.ChangeRotation)
 		// System.Void ET.EventSystem.Publish<object,ET.Client.AfterCreateCurrentScene>(object,ET.Client.AfterCreateCurrentScene)
@@ -366,6 +202,7 @@ public class AOTGenericReferences : UnityEngine.MonoBehaviour
 		// object ET.MongoHelper.FromJson<object>(string)
 		// System.Void ET.MongoHelper.RegisterStruct<ET.LSInput>()
 		// System.Void ET.ObjectHelper.Swap<object>(object&,object&)
+		// object ET.ObjectPool.Fetch<object>()
 		// System.Void ET.RandomGenerator.BreakRank<object>(System.Collections.Generic.List<object>)
 		// string ET.StringHelper.ArrayToString<float>(float[])
 		// object ET.World.AddSingleton<object>()

+ 6 - 3
Unity/Assets/Scripts/Loader/Plugins/HybridCLR/Generated/link.xml

@@ -133,17 +133,18 @@
     <type fullname="ET.MessageDispatcher" preserve="all" />
     <type fullname="ET.MessageHandlerAttribute" preserve="all" />
     <type fullname="ET.MessageHelper" preserve="all" />
-    <type fullname="ET.MessageInnerSender" preserve="all" />
-    <type fullname="ET.MessageInnerSenderSystem" preserve="all" />
     <type fullname="ET.MessageObject" preserve="all" />
     <type fullname="ET.MessageQueue" preserve="all" />
     <type fullname="ET.MongoHelper" preserve="all" />
     <type fullname="ET.NavmeshComponent" preserve="all" />
     <type fullname="ET.NetServices" preserve="all" />
     <type fullname="ET.NetworkHelper" preserve="all" />
+    <type fullname="ET.Object" preserve="all" />
     <type fullname="ET.ObjectHelper" preserve="all" />
     <type fullname="ET.ObjectPool" preserve="all" />
     <type fullname="ET.OpcodeType" preserve="all" />
+    <type fullname="ET.ProcessInnerSender" preserve="all" />
+    <type fullname="ET.ProcessInnerSenderSystem" preserve="all" />
     <type fullname="ET.ProtoObject" preserve="all" />
     <type fullname="ET.RandomGenerator" preserve="all" />
     <type fullname="ET.ResponseTypeAttribute" preserve="all" />
@@ -264,8 +265,11 @@
     <type fullname="System.Console" preserve="all" />
     <type fullname="System.Diagnostics.DebuggableAttribute" preserve="all" />
     <type fullname="System.Diagnostics.DebuggableAttribute/DebuggingModes" preserve="all" />
+    <type fullname="System.Diagnostics.DebuggerBrowsableAttribute" preserve="all" />
+    <type fullname="System.Diagnostics.DebuggerBrowsableState" preserve="all" />
     <type fullname="System.Diagnostics.DebuggerDisplayAttribute" preserve="all" />
     <type fullname="System.Diagnostics.DebuggerHiddenAttribute" preserve="all" />
+    <type fullname="System.Diagnostics.DebuggerStepThroughAttribute" preserve="all" />
     <type fullname="System.Enum" preserve="all" />
     <type fullname="System.Exception" preserve="all" />
     <type fullname="System.Func`1" preserve="all" />
@@ -293,7 +297,6 @@
     <type fullname="System.Runtime.CompilerServices.IsReadOnlyAttribute" preserve="all" />
     <type fullname="System.Runtime.CompilerServices.RuntimeCompatibilityAttribute" preserve="all" />
     <type fullname="System.Runtime.CompilerServices.RuntimeHelpers" preserve="all" />
-    <type fullname="System.Runtime.CompilerServices.TaskAwaiter" preserve="all" />
     <type fullname="System.Runtime.CompilerServices.TaskAwaiter`1" preserve="all" />
     <type fullname="System.Runtime.Versioning.TargetFrameworkAttribute" preserve="all" />
     <type fullname="System.RuntimeFieldHandle" preserve="all" />

+ 8 - 0
Unity/Assets/Scripts/ThirdParty/NativeCollection.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 77e035547760594498156b4f61b7d5c3
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 96 - 0
Unity/Assets/Scripts/ThirdParty/NativeCollection/HashSet.cs

@@ -0,0 +1,96 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+
+namespace NativeCollection
+{
+    public unsafe class HashSet<T>: ICollection<T>, INativeCollectionClass where T : unmanaged, IEquatable<T>
+{
+
+    private UnsafeType.HashSet<T>* _hashSet;
+    private const int _defaultCapacity = 10;
+    public HashSet(int capacity = _defaultCapacity)
+    {
+        _hashSet = UnsafeType.HashSet<T>.Create(capacity);
+        IsDisposed = false;
+    }
+    IEnumerator<T> IEnumerable<T>.GetEnumerator()
+    {
+        return GetEnumerator();
+    }
+
+    IEnumerator IEnumerable.GetEnumerator()
+    {
+        return GetEnumerator();
+    }
+    
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public UnsafeType.HashSet<T>.Enumerator GetEnumerator() => new UnsafeType.HashSet<T>.Enumerator(_hashSet);
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public void Add(T item)
+    {
+        _hashSet->Add(item);
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public void Clear()
+    {
+        _hashSet->Clear();
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public bool Contains(T item)
+    {
+        return _hashSet->Contains(item);
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public void CopyTo(T[] array, int arrayIndex)
+    {
+        _hashSet->CopyTo(array, arrayIndex);
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public bool Remove(T item)
+    {
+        return _hashSet->Remove(item);
+    }
+
+    public int Count => _hashSet->Count;
+    public bool IsReadOnly => false;
+    
+    public void Dispose()
+    {
+        if (IsDisposed)
+        {
+            return;
+        }
+        if (_hashSet!=null)
+        {
+            _hashSet->Dispose();
+            NativeMemoryHelper.Free(_hashSet);
+            GC.RemoveMemoryPressure(Unsafe.SizeOf<UnsafeType.HashSet<T>>());
+            IsDisposed = true;
+        }
+    }
+
+    public void ReInit()
+    {
+        if (IsDisposed)
+        {
+            _hashSet = UnsafeType.HashSet<T>.Create(_defaultCapacity);
+            IsDisposed = false;
+        }
+    }
+
+    public bool IsDisposed { get; private set; }
+
+    ~HashSet()
+    {
+        Dispose();
+    }
+}
+}
+

+ 1 - 1
Unity/Assets/Scripts/Core/SortedCollection.cs.meta → Unity/Assets/Scripts/ThirdParty/NativeCollection/HashSet.cs.meta

@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: bd1f98dab4bd9a34e8da9bea5823fab7
+guid: a15835c961dcd5849b0c33f3131b5c47
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2

+ 12 - 0
Unity/Assets/Scripts/ThirdParty/NativeCollection/INativeCollectionClass.cs

@@ -0,0 +1,12 @@
+using System;
+
+namespace NativeCollection
+{
+    public interface INativeCollectionClass : IDisposable
+    {
+        void ReInit();
+
+        bool IsDisposed { get; }
+    }
+}
+

+ 11 - 0
Unity/Assets/Scripts/ThirdParty/NativeCollection/INativeCollectionClass.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 2c5e583493ff7934ba11c0985384a2db
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 120 - 0
Unity/Assets/Scripts/ThirdParty/NativeCollection/List.cs

@@ -0,0 +1,120 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+
+namespace NativeCollection
+{
+    public unsafe class List<T>: ICollection<T>, INativeCollectionClass where T:unmanaged, IEquatable<T>
+{
+    private UnsafeType.List<T>* _list;
+    private const int _defaultCapacity = 10;
+    public List(int capacity = _defaultCapacity)
+    {
+        _list = UnsafeType.List<T>.Create(capacity);
+        IsDisposed = false;
+    }
+    
+    IEnumerator<T> IEnumerable<T>.GetEnumerator()
+    {
+        return GetEnumerator();
+    }
+
+    IEnumerator IEnumerable.GetEnumerator()
+    {
+        return GetEnumerator();
+    }
+    
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public UnsafeType.List<T>.Enumerator GetEnumerator()
+    {
+        return new UnsafeType.List<T>.Enumerator(_list);
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public void Add(T item)
+    {
+        _list->Add(item);
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public void Clear()
+    {
+        _list->Clear();
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public bool Contains(T item)
+    {
+        return _list->Contains(item);
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public void CopyTo(T[] array, int arrayIndex)
+    {
+        _list->CopyTo(array,arrayIndex);
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public bool Remove(T item)
+    {
+        return _list->Remove(item);
+    }
+    
+    public int Capacity
+    {
+        get => _list->Capacity;
+        set => _list->Capacity = value;
+    }
+    
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public int IndexOf(in T item)
+    {
+        return _list->IndexOf(item);
+    }
+    
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public void RemoveAt(int index)
+    {
+        _list->RemoveAt(index);
+    }
+
+    public ref T this[int index] => ref (*_list)[index];
+
+    public int Count => _list->Count;
+    public bool IsReadOnly => false;
+    
+    public void Dispose()
+    {
+        if (IsDisposed)
+        {
+            return;
+        }
+        if (_list!=null)
+        {
+            _list->Dispose();
+            NativeMemoryHelper.Free(_list);
+            GC.RemoveMemoryPressure(Unsafe.SizeOf<UnsafeType.List<T>>());
+            IsDisposed = true;
+        }
+    }
+    
+    public void ReInit()
+    {
+        if (IsDisposed)
+        {
+            _list = UnsafeType.List<T>.Create(_defaultCapacity);
+            IsDisposed = false;
+        }
+    }
+
+    public bool IsDisposed { get; private set; }
+
+    ~List()
+    {
+        Dispose();
+    }
+}
+}
+
+

+ 11 - 0
Unity/Assets/Scripts/ThirdParty/NativeCollection/List.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 8268fb22100eff945b4afe255bacc0ea
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 98 - 0
Unity/Assets/Scripts/ThirdParty/NativeCollection/MultiMap.cs

@@ -0,0 +1,98 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+using NativeCollection.UnsafeType;
+
+namespace NativeCollection
+{
+    public unsafe class MultiMap<T, K> : IEnumerable<MultiMapPair<T, K>>, INativeCollectionClass
+    where T : unmanaged, IEquatable<T>, IComparable<T> where K : unmanaged, IEquatable<K>
+{
+    private UnsafeType.MultiMap<T, K>* _multiMap;
+
+    private const int _defaultPoolSize = 200;
+    
+    public MultiMap(int maxPoolSize = _defaultPoolSize)
+    {
+        _multiMap = UnsafeType.MultiMap<T, K>.Create(maxPoolSize);
+        IsDisposed = false;
+    }
+    
+    public Span<K> this[T key] => (*_multiMap)[key];
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public void Add(T key, K value)
+    {
+        _multiMap->Add(key,value);
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public bool Remove(T key, K value)
+    {
+        return _multiMap->Remove(key, value);
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public bool Remove(T key)
+    {
+        return _multiMap->Remove(key);
+    }
+    
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public void Clear()
+    {
+        _multiMap->Clear();
+    }
+
+    public int Count => _multiMap->Count;
+    
+    IEnumerator<MultiMapPair<T, K>> IEnumerable<MultiMapPair<T, K>>. GetEnumerator()
+    {
+        return GetEnumerator();
+    }
+
+    IEnumerator IEnumerable.GetEnumerator()
+    {
+        return GetEnumerator();
+    }
+    
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public UnsafeType.SortedSet<MultiMapPair<T, K>>.Enumerator GetEnumerator()
+    {
+        return _multiMap->GetEnumerator();
+    }
+
+    public void Dispose()
+    {
+        if (IsDisposed)
+        {
+            return;
+        }
+        if (_multiMap!=null)
+        {
+            _multiMap->Dispose();
+            NativeMemoryHelper.Free(_multiMap);
+            GC.RemoveMemoryPressure(Unsafe.SizeOf<UnsafeType.MultiMap<T,K>>());
+            IsDisposed = true;
+        }
+    }
+
+    public void ReInit()
+    {
+        if (IsDisposed)
+        {
+            _multiMap = UnsafeType.MultiMap<T, K>.Create(_defaultPoolSize);
+            IsDisposed = false;
+        }
+    }
+
+    public bool IsDisposed { get; private set; }
+    
+    ~MultiMap()
+    {
+        Dispose();
+    }
+}
+}
+

+ 11 - 0
Unity/Assets/Scripts/ThirdParty/NativeCollection/MultiMap.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: f598fd478a458cf4aa415d8612326f29
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 70 - 0
Unity/Assets/Scripts/ThirdParty/NativeCollection/NativeMemoryHelper.cs

@@ -0,0 +1,70 @@
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace NativeCollection
+{
+    public static unsafe class NativeMemoryHelper
+    {
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static void* Alloc(UIntPtr byteCount)
+        {
+            GC.AddMemoryPressure((long)byteCount);
+#if NET6_0_OR_GREATER
+            return NativeMemory.Alloc(byteCount);
+#else
+        return Marshal.AllocHGlobal((int)byteCount).ToPointer();
+#endif
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static void* Alloc(UIntPtr elementCount, UIntPtr elementSize)
+        {
+            GC.AddMemoryPressure((long)((long)elementCount * (long)elementSize));
+#if NET6_0_OR_GREATER
+            return NativeMemory.Alloc(elementCount, elementSize);
+#else
+        return Marshal.AllocHGlobal((int)((int)elementCount*(int)elementSize)).ToPointer();
+#endif
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static void* AllocZeroed(UIntPtr byteCount)
+        {
+            GC.AddMemoryPressure((long)byteCount);
+#if NET6_0_OR_GREATER
+            return NativeMemory.AllocZeroed(byteCount);
+#else
+        var ptr = Marshal.AllocHGlobal((int)byteCount).ToPointer();
+        Unsafe.InitBlockUnaligned(ptr,0,(uint)byteCount);
+        return ptr;
+#endif
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static void* AllocZeroed(UIntPtr elementCount, UIntPtr elementSize)
+        {
+            GC.AddMemoryPressure((long)((long)elementCount * (long)elementSize));
+        
+#if NET6_0_OR_GREATER
+            return NativeMemory.AllocZeroed(elementCount, elementSize);
+#else
+        var ptr = Marshal.AllocHGlobal((int)((int)elementCount*(int)elementSize)).ToPointer();
+        Unsafe.InitBlockUnaligned(ptr,0,(uint)((uint)elementCount*(uint)elementSize));
+        return ptr;
+#endif
+        }
+
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static void Free<T>(T* ptr) where T : unmanaged
+        {
+#if NET6_0_OR_GREATER
+            NativeMemory.Free(ptr);
+#else
+        Marshal.FreeHGlobal(new IntPtr(ptr));
+#endif
+        }
+    }    
+}
+

+ 11 - 0
Unity/Assets/Scripts/ThirdParty/NativeCollection/NativeMemoryHelper.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 0ff308e9138cfc34d94db978b532f6e3
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 57 - 0
Unity/Assets/Scripts/ThirdParty/NativeCollection/NativePool.cs

@@ -0,0 +1,57 @@
+using System;
+using System.Runtime.CompilerServices;
+using NativeCollection.UnsafeType;
+
+namespace NativeCollection
+{
+    public unsafe class NativePool<T> : INativeCollectionClass where T: unmanaged,IEquatable<T>,IPool
+    {
+        private UnsafeType.NativePool<T>* _nativePool;
+        private const int _defaultPoolSize = 200;
+    
+        public NativePool(int maxPoolSize = _defaultPoolSize)
+        {
+            _nativePool = UnsafeType.NativePool<T>.Create(maxPoolSize);
+            IsDisposed = false;
+        }
+        
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public T* Alloc()
+        {
+            return _nativePool->Alloc();
+        }
+    
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void Return(T* ptr)
+        {
+            _nativePool->Return(ptr);
+        }
+        
+        public void Dispose()
+        {
+            if (IsDisposed)
+            {
+                return;
+            }
+            if (_nativePool != null)
+            {
+                _nativePool->Dispose();
+                NativeMemoryHelper.Free(_nativePool);
+                GC.RemoveMemoryPressure(Unsafe.SizeOf<UnsafeType.NativePool<T>>());
+                IsDisposed = true;
+            }
+        }
+        
+        public void ReInit()
+        {
+            if (IsDisposed)
+            {
+                _nativePool = UnsafeType.NativePool<T>.Create(_defaultPoolSize);
+                IsDisposed = false;
+            }
+        }
+    
+        public bool IsDisposed { get; private set; }
+    }
+}
+

+ 11 - 0
Unity/Assets/Scripts/ThirdParty/NativeCollection/NativePool.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 6354c4f8813382145b5de56c94cc1143
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 88 - 0
Unity/Assets/Scripts/ThirdParty/NativeCollection/Queue.cs

@@ -0,0 +1,88 @@
+using System;
+using System.Runtime.CompilerServices;
+
+namespace NativeCollection
+{
+    public unsafe class Queue<T> : INativeCollectionClass where T : unmanaged
+    {
+        private UnsafeType.Queue<T>* _queue;
+    
+        public Queue(int capacity = 10)
+        {
+            _queue = UnsafeType.Queue<T>.Create(capacity);
+            IsDisposed = false;
+        }
+    
+        public int Count => _queue->Count;
+    
+        public void Dispose()
+        {
+            if (IsDisposed)
+            {
+                return;
+            }
+            if (_queue != null)
+            {
+                _queue->Dispose();
+                NativeMemoryHelper.Free(_queue);
+                GC.RemoveMemoryPressure(Unsafe.SizeOf<UnsafeType.Queue<T>>());
+                IsDisposed = true;
+            }
+        }
+    
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void Clear()
+        {
+            _queue->Clear();
+        }
+    
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void Enqueue(in T item)
+        {
+            _queue->Enqueue(item);
+        }
+    
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public T Dequeue()
+        {
+            return _queue->Dequeue();
+        }
+    
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public bool TryDequeue(out T result)
+        {
+            var value = _queue->TryDequeue(out result);
+            return value;
+        }
+    
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public T Peek()
+        {
+            return _queue->Peek();
+        }
+    
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public bool TryPeek(out T result)
+        {
+            var value = _queue->TryPeek(out result);
+            return value;
+        }
+    
+        ~Queue()
+        {
+            Dispose();
+        }
+    
+        public void ReInit()
+        {
+            if (IsDisposed)
+            {
+                _queue = UnsafeType.Queue<T>.Create();
+                IsDisposed = false;
+            }
+        }
+    
+        public bool IsDisposed { get; private set; }
+    }
+}
+

+ 11 - 0
Unity/Assets/Scripts/ThirdParty/NativeCollection/Queue.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 8ce81c4989ffc4a418025bf2672b9e4d
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 101 - 0
Unity/Assets/Scripts/ThirdParty/NativeCollection/SortedSet.cs

@@ -0,0 +1,101 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+
+namespace NativeCollection
+{
+    public unsafe class SortedSet<T> : ICollection<T>, INativeCollectionClass where T : unmanaged, IEquatable<T>,IComparable<T>
+{
+    private UnsafeType.SortedSet<T>* _sortedSet;
+    private const int _defaultNodePoolSize = 200;
+    public SortedSet(int nodePoolSize = _defaultNodePoolSize)
+    {
+        _sortedSet = UnsafeType.SortedSet<T>.Create(nodePoolSize);
+        IsDisposed = false;
+    }
+    IEnumerator<T> IEnumerable<T>.GetEnumerator()
+    {
+        return GetEnumerator();
+    }
+
+    IEnumerator IEnumerable.GetEnumerator()
+    {
+        return GetEnumerator();
+    }
+    
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public UnsafeType.SortedSet<T>.Enumerator GetEnumerator()
+    {
+        return new UnsafeType.SortedSet<T>.Enumerator(_sortedSet);
+    }
+
+    void ICollection<T>.Add(T item)
+    {
+        _sortedSet->Add(item);
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public bool Add(T item)
+    {
+        return _sortedSet->Add(item);
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public void Clear()
+    {
+        _sortedSet->Clear();
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public bool Contains(T item)
+    {
+        return _sortedSet->Contains(item);
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public void CopyTo(T[] array, int arrayIndex)
+    {
+        _sortedSet->CopyTo(array,arrayIndex);
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public bool Remove(T item)
+    {
+        return _sortedSet->Remove(item);
+    }
+    
+    public T? Min => _sortedSet->Min;
+    
+    public T? Max => _sortedSet->Max;
+
+    public int Count => _sortedSet->Count;
+    public bool IsReadOnly => false;
+    public void Dispose()
+    {
+        if (IsDisposed)
+        {
+            return;
+        }
+        if (_sortedSet!=null)
+        {
+            _sortedSet->Dispose();
+            NativeMemoryHelper.Free(_sortedSet);
+            GC.RemoveMemoryPressure(Unsafe.SizeOf<UnsafeType.SortedSet<T>>());
+            IsDisposed = true;
+        }
+    }
+
+    public void ReInit()
+    {
+        if (IsDisposed)
+        {
+            _sortedSet = UnsafeType.SortedSet<T>.Create(_defaultNodePoolSize);
+            IsDisposed = false;
+        }
+    }
+
+    public bool IsDisposed { get; private set; }
+}
+}
+

+ 11 - 0
Unity/Assets/Scripts/ThirdParty/NativeCollection/SortedSet.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 066280cf88790f141b3b0803dc4bfde9
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 88 - 0
Unity/Assets/Scripts/ThirdParty/NativeCollection/Stack.cs

@@ -0,0 +1,88 @@
+using System;
+using System.Runtime.CompilerServices;
+
+namespace NativeCollection
+{
+    public unsafe class Stack<T> : INativeCollectionClass where T : unmanaged
+    {
+        private const int _defaultCapacity = 10;
+        private UnsafeType.Stack<T>* _stack;
+    
+        public Stack(int initialCapacity = _defaultCapacity)
+        {
+            _stack = UnsafeType.Stack<T>.Create(initialCapacity);
+            IsDisposed = false;
+        }
+    
+        public int Count => _stack->Count;
+    
+        public void Dispose()
+        {
+            if (IsDisposed)
+            {
+                return;
+            }
+            if (_stack != null)
+            {
+                _stack->Dispose();
+                NativeMemoryHelper.Free(_stack);
+                GC.RemoveMemoryPressure(Unsafe.SizeOf<UnsafeType.Stack<T>>());
+                IsDisposed = true;
+            }
+        }
+    
+        public void Clear()
+        {
+            _stack->Clear();
+        }
+    
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public bool Contains(in T obj)
+        {
+            return _stack->Contains(obj);
+        }
+    
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public T Peak()
+        {
+            return _stack->Peak();
+        }
+    
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public T Pop()
+        {
+            return _stack->Pop();
+        }
+    
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public bool TryPop(out T result)
+        {
+            var returnValue = _stack->TryPop(out result);
+            return returnValue;
+        }
+    
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void Push(in T obj)
+        {
+            _stack->Push(obj);
+        }
+    
+        ~Stack()
+        {
+            Dispose();
+        }
+    
+        public void ReInit()
+        {
+            if (IsDisposed)
+            {
+                _stack = UnsafeType.Stack<T>.Create(_defaultCapacity);
+                IsDisposed = false;
+            }
+        }
+    
+        public bool IsDisposed { get; private set; }
+    }
+}
+
+

+ 11 - 0
Unity/Assets/Scripts/ThirdParty/NativeCollection/Stack.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 1654b8a9e4a787043ae124e4b2734955
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 84 - 0
Unity/Assets/Scripts/ThirdParty/NativeCollection/ThrowHelper.cs

@@ -0,0 +1,84 @@
+using System;
+using System.Diagnostics.CodeAnalysis;
+
+namespace NativeCollection
+{
+    internal static class ThrowHelper
+    {
+        [DoesNotReturn]
+        public static void StackInitialCapacityException()
+        {
+            throw new ArgumentOutOfRangeException();
+        }
+    
+        [DoesNotReturn]
+        public static void StackEmptyException()
+        {
+            throw new InvalidOperationException("Stack Empty");
+        }
+    
+        [DoesNotReturn]
+        public static void QueueEmptyException()
+        {
+            throw new InvalidOperationException("EmptyQueue");
+        }
+    
+        [DoesNotReturn]
+        public static void ListInitialCapacityException()
+        {
+            throw new ArgumentOutOfRangeException();
+        }
+    
+        [DoesNotReturn]
+        public static void IndexMustBeLessException()
+        {
+            throw new ArgumentOutOfRangeException("IndexMustBeLess");
+        }
+    
+    
+        [DoesNotReturn]
+        public static void ListSmallCapacity()
+        {
+            throw new ArgumentOutOfRangeException("SmallCapacity");
+        }
+    
+    
+        [DoesNotReturn]
+        public static void ListIndexOutOfRange()
+        {
+            throw new ArgumentOutOfRangeException("ListIndexOutOfRange");
+        }
+        
+        
+        [DoesNotReturn]
+        public static void ConcurrentOperationsNotSupported()
+        {
+            throw new InvalidOperationException("ConcurrentOperationsNotSupported");
+        }
+        
+        [DoesNotReturn]
+        public static void HashSetCapacityOutOfRange()
+        {
+            throw new ArgumentOutOfRangeException("HashSetCapacityOutOfRange");
+        }
+        
+        [DoesNotReturn]
+        public static void HashSetEnumFailedVersion()
+        {
+            throw new InvalidOperationException("EnumFailedVersion");
+        }
+        
+        [DoesNotReturn]
+        public static void HashSetEnumOpCantHappen()
+        {
+            throw new InvalidOperationException("EnumOpCantHappen");
+        }
+
+        [DoesNotReturn]
+        public static void SortedSetVersionChanged()
+        {
+            throw new InvalidOperationException("_version != _tree.version");
+        }
+    }
+}
+

+ 11 - 0
Unity/Assets/Scripts/ThirdParty/NativeCollection/ThrowHelper.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 8d054f5cda699e145b0b2487f6c5b196
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 8 - 0
Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: a3c063db0b2faf84da298e2c6fb2bcf8
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 76 - 0
Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/Dictionary.cs

@@ -0,0 +1,76 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace NativeCollection.UnsafeType
+{
+    public unsafe struct Dictionary<TKey, TValue> : IDictionary<TKey, TValue> where TKey : unmanaged, IEquatable<TKey> where TValue : unmanaged, IEquatable<TValue>
+    {
+        public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
+        {
+            throw new NotImplementedException();
+        }
+    
+        IEnumerator IEnumerable.GetEnumerator()
+        {
+            return GetEnumerator();
+        }
+    
+        public void Add(KeyValuePair<TKey, TValue> item)
+        {
+            throw new NotImplementedException();
+        }
+       
+        public void Clear()
+        {
+            throw new NotImplementedException();
+        }
+    
+        public bool Contains(KeyValuePair<TKey, TValue> item)
+        {
+            throw new NotImplementedException();
+        }
+    
+        public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
+        {
+            throw new NotImplementedException();
+        }
+    
+        public bool Remove(KeyValuePair<TKey, TValue> item)
+        {
+            throw new NotImplementedException();
+        }
+    
+        public int Count { get; }
+        public bool IsReadOnly { get; }
+        public void Add(TKey key, TValue value)
+        {
+            throw new NotImplementedException();
+        }
+    
+        public bool ContainsKey(TKey key)
+        {
+            throw new NotImplementedException();
+        }
+    
+        public bool Remove(TKey key)
+        {
+            throw new NotImplementedException();
+        }
+    
+        public bool TryGetValue(TKey key, out TValue value)
+        {
+            throw new NotImplementedException();
+        }
+    
+        public TValue this[TKey key]
+        {
+            get => throw new NotImplementedException();
+            set => throw new NotImplementedException();
+        }
+    
+        public ICollection<TKey> Keys { get; }
+        public ICollection<TValue> Values { get; }
+    }
+}
+

+ 11 - 0
Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/Dictionary.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 49e35b184dd60c64f8593512d7018a28
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 133 - 0
Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/HashHelpers.cs

@@ -0,0 +1,133 @@
+using System;
+
+namespace NativeCollection.UnsafeType
+{
+    public static class HashHelpers
+{
+    public const uint HashCollisionThreshold = 100;
+
+    // This is the maximum prime smaller than Array.MaxLength.
+    public const int MaxPrimeArrayLength = 0x7FFFFFC3;
+
+    public const int HashPrime = 101;
+    
+    private static readonly int[] s_primes = new int[72]
+    {
+        3,
+        7,
+        11,
+        17,
+        23,
+        29,
+        37,
+        47,
+        59,
+        71,
+        89,
+        107,
+        131,
+        163,
+        197,
+        239,
+        293,
+        353,
+        431,
+        521,
+        631,
+        761,
+        919,
+        1103,
+        1327,
+        1597,
+        1931,
+        2333,
+        2801,
+        3371,
+        4049,
+        4861,
+        5839,
+        7013,
+        8419,
+        10103,
+        12143,
+        14591,
+        17519,
+        21023,
+        25229,
+        30293,
+        36353,
+        43627,
+        52361,
+        62851,
+        75431,
+        90523,
+        108631,
+        130363,
+        156437,
+        187751,
+        225307,
+        270371,
+        324449,
+        389357,
+        467237,
+        560689,
+        672827,
+        807403,
+        968897,
+        1162687,
+        1395263,
+        1674319,
+        2009191,
+        2411033,
+        2893249,
+        3471899,
+        4166287,
+        4999559,
+        5999471,
+        7199369
+    };
+    
+    public static bool IsPrime(int candidate)
+    {
+        if ((candidate & 1) == 0)
+            return candidate == 2;
+        int num = (int) Math.Sqrt((double) candidate);
+        for (int index = 3; index <= num; index += 2)
+        {
+            if (candidate % index == 0)
+                return false;
+        }
+        return true;
+    }
+
+    public static int GetPrime(int min)
+    {
+        if (min < 0)
+            throw new ArgumentException("SR.Arg_HTCapacityOverflow");
+        foreach (int prime in HashHelpers.s_primes)
+        {
+            if (prime >= min)
+                return prime;
+        }
+        for (int candidate = min | 1; candidate < int.MaxValue; candidate += 2)
+        {
+            if (HashHelpers.IsPrime(candidate) && (candidate - 1) % 101 != 0)
+                return candidate;
+        }
+        return min;
+    }
+    
+    public static int ExpandPrime(int oldSize)
+    {
+        int min = 2 * oldSize;
+        return (uint) min > 2147483587U && 2147483587 > oldSize ? 2147483587 : HashHelpers.GetPrime(min);
+    }
+    
+    /// <summary>Returns approximate reciprocal of the divisor: ceil(2**64 / divisor).</summary>
+    /// <remarks>This should only be used on 64-bit.</remarks>
+    public static ulong GetFastModMultiplier(uint divisor) =>
+        ulong.MaxValue / divisor + 1;
+    
+}
+}
+

+ 11 - 0
Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/HashHelpers.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: c7c74eceab447c343b7901fbf7e755e6
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 476 - 0
Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/HashSet.cs

@@ -0,0 +1,476 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+using System.Text;
+
+namespace NativeCollection.UnsafeType
+{
+    public unsafe struct HashSet<T> : ICollection<T>, IDisposable where T : unmanaged, IEquatable<T>
+{
+    /// <summary>Cutoff point for stackallocs. This corresponds to the number of ints.</summary>
+    private const int StackAllocThreshold = 100;
+
+    /// <summary>
+    ///     When constructing a hashset from an existing collection, it may contain duplicates,
+    ///     so this is used as the max acceptable excess ratio of capacity to count. Note that
+    ///     this is only used on the ctor and not to automatically shrink if the hashset has, e.g,
+    ///     a lot of adds followed by removes. Users must explicitly shrink by calling TrimExcess.
+    ///     This is set to 3 because capacity is acceptable as 2x rounded up to nearest prime.
+    /// </summary>
+    private const int ShrinkThreshold = 3;
+
+    private const int StartOfFreeList = -3;
+
+    private HashSet<T>* _self;
+    private int* _buckets;
+    private int _bucketLength;
+    private Entry* _entries;
+    private int _entryLength;
+#if TARGET_64BIT
+        private ulong _fastModMultiplier;
+#endif
+    private int _count;
+    private int _freeList;
+    private int _freeCount;
+    private int _version;
+    private static IEqualityComparer<T> _comparer = EqualityComparer<T>.Default;
+
+    public static HashSet<T>* Create(int capacity = 0)
+    {
+        HashSet<T>* hashSet = (HashSet<T>*)NativeMemoryHelper.Alloc((UIntPtr)Unsafe.SizeOf<HashSet<T>>());
+        hashSet->_buckets = null;
+        hashSet->_entries = null;
+        hashSet->_self = hashSet;
+        hashSet->Initialize(capacity);
+        return hashSet;
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public bool Add(T item) => AddIfNotPresent(item, out _);
+
+    IEnumerator<T> IEnumerable<T>.GetEnumerator()
+    {
+        return GetEnumerator();
+    }
+
+    IEnumerator IEnumerable.GetEnumerator()
+    {
+        return GetEnumerator();
+    }
+    
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public Enumerator GetEnumerator() => new Enumerator(_self);
+
+    #region ICollection<T> methods
+
+    void ICollection<T>.Add(T item)
+    {
+        AddIfNotPresent(item, out _);
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public void Clear()
+    {
+        int count = _count;
+        if (count > 0)
+        {
+            Debug.Assert(_buckets != null, "_buckets should be non-null");
+            Debug.Assert(_entries != null, "_entries should be non-null");
+            Unsafe.InitBlockUnaligned(_buckets,0,(uint)(Unsafe.SizeOf<int>()*_bucketLength));
+            Unsafe.InitBlockUnaligned(_entries,0,(uint)(Unsafe.SizeOf<int>()*count));
+            _count = 0;
+            _freeList = -1;
+            _freeCount = 0;
+        }
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public bool Contains(T item)
+    {
+        return FindItemIndex(item) >= 0;
+    }
+
+    #endregion
+
+    
+    public void CopyTo(T[] array, int arrayIndex)
+    {
+        throw new NotImplementedException();
+    }
+    
+    public bool Remove(T item)
+    {
+        //if (_buckets == null) return false;
+        var entries = _entries;
+        Debug.Assert(entries != null, "entries should be non-null");
+
+        uint collisionCount = 0;
+        int last = -1;
+        int hashCode = item.GetHashCode();
+
+        ref int bucket = ref GetBucketRef(hashCode);
+        int i = bucket - 1; // Value in buckets is 1-based
+
+        while (i >= 0)
+        {
+            ref Entry entry = ref entries[i];
+
+            if (entry.HashCode == hashCode && (item.Equals(entry.Value)))
+            {
+                if (last < 0)
+                {
+                    bucket = entry.Next + 1; // Value in buckets is 1-based
+                }
+                else
+                {
+                    entries[last].Next = entry.Next;
+                }
+
+                Debug.Assert((StartOfFreeList - _freeList) < 0, "shouldn't underflow because max hashtable length is MaxPrimeArrayLength = 0x7FEFFFFD(2146435069) _freelist underflow threshold 2147483646");
+                entry.Next = StartOfFreeList - _freeList;
+
+                _freeList = i;
+                _freeCount++;
+                return true;
+            }
+
+            last = i;
+            i = entry.Next;
+
+            collisionCount++;
+            if (collisionCount > (uint)_entryLength)
+            {
+                // The chain of entries forms a loop; which means a concurrent update has happened.
+                // Break out of the loop and throw, rather than looping forever.
+                ThrowHelper.ConcurrentOperationsNotSupported();
+            }
+        }
+
+        return false;
+    }
+
+    public int Count => _count - _freeCount;
+    bool ICollection<T>.IsReadOnly => false;
+
+    public void Dispose()
+    {
+        NativeMemoryHelper.Free(_buckets);
+        GC.RemoveMemoryPressure(Unsafe.SizeOf<int>()*_bucketLength);
+        
+        NativeMemoryHelper.Free(_entries);
+        GC.RemoveMemoryPressure(Unsafe.SizeOf<Entry>()*_entryLength);
+    }
+    
+    #region Helper methods
+    
+    /// <summary>
+    /// Initializes buckets and slots arrays. Uses suggested capacity by finding next prime
+    /// greater than or equal to capacity.
+    /// </summary>
+    private int Initialize(int capacity)
+    {
+        int size = HashHelpers.GetPrime(capacity);
+        _buckets = (int*)NativeMemoryHelper.AllocZeroed((UIntPtr)(Unsafe.SizeOf<int>() * size));
+        _bucketLength = size;
+        _entries = (Entry*)NativeMemoryHelper.AllocZeroed((UIntPtr)(Unsafe.SizeOf<Entry>() * size));
+        _entryLength = size;
+        // Assign member variables after both arrays are allocated to guard against corruption from OOM if second fails.
+        _freeList = -1;
+        _freeCount = 0;
+        _count = 0;
+        _version = 0;
+#if TARGET_64BIT
+            _fastModMultiplier = HashHelpers.GetFastModMultiplier((uint)size);
+#endif
+
+        return size;
+    }
+    
+    /// <summary>Adds the specified element to the set if it's not already contained.</summary>
+    /// <param name="value">The element to add to the set.</param>
+    /// <param name="location">The index into <see cref="_entries" /> of the element.</param>
+    /// <returns>true if the element is added to the <see cref="HashSet{T}" /> object; false if the element is already present.</returns>
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    private bool AddIfNotPresent(T value, out int location)
+    {
+        //Console.WriteLine($"AddIfNotPresent:{value}");
+        //if (_buckets == null) Initialize(0);
+        Debug.Assert(_buckets != null);
+
+        Entry* entries = _entries;
+        Debug.Assert(entries != null, "expected entries to be non-null");
+
+        //var comparer = _comparer;
+        int hashCode;
+
+        uint collisionCount = 0;
+        ref var bucket = ref Unsafe.NullRef<int>();
+        
+        hashCode =  value.GetHashCode();
+        bucket = ref GetBucketRef(hashCode);
+        
+        var i = bucket - 1; // Value in _buckets is 1-based
+        // Console.WriteLine($"i:{i}");
+        while (i >= 0)
+        {
+            // Console.WriteLine($"i:{i}");
+            ref Entry entry = ref _entries[i];
+            // Console.WriteLine($"entry.HashCode:{entry.HashCode} hashCode:{hashCode} Equals:{comparer.Equals(entry.Value, value)}");
+            if (entry.HashCode == hashCode && value.Equals(value))
+            {
+                location = i;
+                return false;
+            }
+
+            i = entry.Next;
+
+            collisionCount++;
+            // Console.WriteLine($"collisionCount :{collisionCount} i:{i}");
+            if (collisionCount > (uint)_entryLength)
+                // The chain of entries forms a loop, which means a concurrent update has happened.
+                ThrowHelper.ConcurrentOperationsNotSupported();
+        }
+        
+
+        int index;
+        if (_freeCount > 0)
+        {
+            index = _freeList;
+            _freeCount--;
+            Debug.Assert(StartOfFreeList - _entries[_freeList].Next >= -1,
+                "shouldn't overflow because `next` cannot underflow");
+            _freeList = StartOfFreeList - _entries[_freeList].Next;
+        }
+        else
+        {
+            var count = _count;
+            if (count == _entryLength)
+            {
+                Resize();
+                bucket = ref GetBucketRef(hashCode);
+            }
+
+            index = count;
+            _count = count + 1;
+        }
+
+        {
+            ref Entry entry = ref _entries[index];
+            entry.HashCode = hashCode;
+            entry.Next = bucket - 1; // Value in _buckets is 1-based
+            entry.Value = value;
+            bucket = index + 1;
+            _version++;
+            location = index;
+        }
+        
+        return true;
+    }
+        
+        /// <summary>Gets a reference to the specified hashcode's bucket, containing an index into <see cref="_entries"/>.</summary>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        private ref int GetBucketRef(int hashCode)
+        {
+            //var buckets = _buckets;
+            
+#if TARGET_64BIT
+            return ref _buckets[HashHelpers.FastMod((uint)hashCode, (uint)_buckets.Length, _fastModMultiplier)];
+#else
+            int index = (int)((uint)hashCode %(uint)_bucketLength);
+            return ref _buckets[index];
+#endif
+        }
+
+    #endregion
+
+    
+
+            /// <summary>Ensures that this hash set can hold the specified number of elements without growing.</summary>
+        public int EnsureCapacity(int capacity)
+        {
+            if (capacity < 0)
+            {
+                ThrowHelper.HashSetCapacityOutOfRange();
+            }
+
+            int currentCapacity = _entries == null ? 0 : _entryLength;
+            if (currentCapacity >= capacity)
+            {
+                return currentCapacity;
+            }
+
+            if (_buckets == null)
+            {
+                return Initialize(capacity);
+            }
+
+            int newSize = HashHelpers.GetPrime(capacity);
+            Resize(newSize, forceNewHashCodes: false);
+            return newSize;
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        private void Resize() => Resize(HashHelpers.ExpandPrime(_count), forceNewHashCodes: false);
+
+        private void Resize(int newSize, bool forceNewHashCodes)
+        {
+            // Console.WriteLine($"before resize:{*self}");
+            // Value types never rehash
+            Debug.Assert(!forceNewHashCodes || !typeof(T).IsValueType);
+            Debug.Assert(_entries != null, "_entries should be non-null");
+            Debug.Assert(newSize >= _entryLength);
+            // Console.WriteLine($"Resize newSize:{newSize} byteSize:{Unsafe.SizeOf<Entry>() * newSize}");
+            var newEntries = (Entry*)NativeMemoryHelper.AllocZeroed((UIntPtr)(Unsafe.SizeOf<Entry>() * newSize));
+            Unsafe.CopyBlockUnaligned(newEntries,_entries,(uint)(Unsafe.SizeOf<Entry>()*_entryLength));
+            int count = _count;
+            // Assign member variables after both arrays allocated to guard against corruption from OOM if second fails
+            var newBucket = (int*)NativeMemoryHelper.AllocZeroed((UIntPtr)(Unsafe.SizeOf<int>() * newSize));
+            NativeMemoryHelper.Free(_buckets);
+            GC.RemoveMemoryPressure(Unsafe.SizeOf<int>()*_bucketLength);
+            _buckets = newBucket;
+            _bucketLength = newSize;
+#if TARGET_64BIT
+            _fastModMultiplier = HashHelpers.GetFastModMultiplier((uint)newSize);
+#endif
+            for (int i = 0; i < count; i++)
+            {
+                ref Entry entry = ref newEntries[i];
+                if (entry.Next >= -1)
+                {
+                    ref int bucket = ref GetBucketRef(entry.HashCode);
+                    entry.Next = bucket - 1; // Value in _buckets is 1-based
+                    // Console.WriteLine($"entry.Next:{entry.Next} bucket:{bucket}");
+                    bucket = i + 1;
+                }
+            }
+            NativeMemoryHelper.Free(_entries);
+            GC.RemoveMemoryPressure(Unsafe.SizeOf<Entry>()*_entryLength);
+            _entries = newEntries;
+            _entryLength = newSize;
+            
+            //Console.WriteLine($"after resize:{*self} totalSize:{_entryLength}");
+        }
+        
+        /// <summary>Gets the index of the item in <see cref="_entries"/>, or -1 if it's not in the set.</summary>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        private int FindItemIndex(T item)
+        {
+            //if (_buckets == null) return -1;
+            var entries = _entries;
+            Debug.Assert(entries != null, "Expected _entries to be initialized");
+
+            uint collisionCount = 0;
+            //IEqualityComparer<T>? comparer = _comparer;
+            
+            int hashCode = item.GetHashCode();
+            int i = GetBucketRef(hashCode) - 1; // Value in _buckets is 1-based
+            while (i >= 0)
+            {
+                ref Entry entry = ref entries[i];
+                if (entry.HashCode == hashCode && item.Equals(entry.Value))
+                {
+                    return i;
+                }
+                i = entry.Next;
+
+                collisionCount++;
+                if (collisionCount > (uint)_entryLength)
+                {
+                    // The chain of entries forms a loop, which means a concurrent update has happened.
+                    ThrowHelper.ConcurrentOperationsNotSupported();
+                }
+            }
+
+            return -1;
+        }
+
+    
+    private struct Entry : IEquatable<Entry>
+    {
+        public int HashCode;
+
+        /// <summary>
+        /// 0-based index of next entry in chain: -1 means end of chain
+        /// also encodes whether this entry _itself_ is part of the free list by changing sign and subtracting 3,
+        /// so -2 means end of free list, -3 means index 0 but on free list, -4 means index 1 but on free list, etc.
+        /// </summary>
+        public int Next;
+        
+        public T Value;
+        public bool Equals(Entry other)
+        {
+            return HashCode == other.HashCode && Next == other.Next && Value.Equals(other.Value);
+        }
+    }
+
+    public override string ToString()
+    {
+        StringBuilder sb = new StringBuilder();
+        foreach (var value in *_self)
+        {
+            sb.Append($"{value} ");
+        }
+
+        sb.Append("\n");
+        return sb.ToString();
+    }
+
+    public struct Enumerator : IEnumerator<T>
+    {
+        private readonly HashSet<T>* _hashSet;
+        private readonly int _version;
+        private int _index;
+        private T _current;
+
+        internal Enumerator(HashSet<T>* hashSet)
+        {
+            _hashSet = hashSet;
+            _version = hashSet->_version;
+            _index = 0;
+            _current = default!;
+        }
+
+        public bool MoveNext()
+        {
+            if (_version != _hashSet->_version)
+                ThrowHelper.HashSetEnumFailedVersion();
+            
+            // Use unsigned comparison since we set index to dictionary.count+1 when the enumeration ends.
+            // dictionary.count+1 could be negative if dictionary.count is int.MaxValue
+            while ((uint)_index < (uint)_hashSet->_count)
+            {
+                ref Entry entry = ref _hashSet->_entries[_index++];
+                if (entry.Next >= -1)
+                {
+                    _current = entry.Value;
+                    return true;
+                }
+            }
+
+            _index = _hashSet->_count + 1;
+            _current = default!;
+            return false;
+        }
+
+        public T Current => _current;
+
+        public void Dispose()
+        {
+        }
+        
+        object IEnumerator.Current => Current;
+        
+        public void Reset()
+        {
+            if (_version != _hashSet->_version)
+                ThrowHelper.HashSetEnumFailedVersion();
+
+            _index = 0;
+            _current = default!;
+        }
+    }
+}
+}
+

+ 11 - 0
Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/HashSet.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 2b4b14c481e44834fb887815ce43c0d3
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 363 - 0
Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/List.cs

@@ -0,0 +1,363 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+using System.Text;
+
+namespace NativeCollection.UnsafeType
+{
+    public unsafe struct List<T> : ICollection<T>, IDisposable, IPool where T : unmanaged, IEquatable<T>
+{
+    private List<T>* self;
+
+    private int _arrayLength;
+
+    private T* _items;
+
+    private const int _defaultCapacity = 4;
+
+    public static List<T>* Create(int initialCapacity = _defaultCapacity)
+    {
+        if (initialCapacity < 0) ThrowHelper.ListInitialCapacityException();
+
+        var list = (List<T>*)NativeMemoryHelper.Alloc((UIntPtr)Unsafe.SizeOf<List<T>>());
+
+        if (initialCapacity < _defaultCapacity)
+            initialCapacity = _defaultCapacity; // Simplify doubling logic in Push.
+
+        list->_items = (T*)NativeMemoryHelper.Alloc((UIntPtr)initialCapacity, (UIntPtr)Unsafe.SizeOf<T>());
+        list->_arrayLength = initialCapacity;
+        list->Count = 0;
+        list->self = list;
+        return list;
+    }
+
+    
+    public ref T this[int index]
+    {
+        get
+        {
+            if (index>=Count)
+            {
+                ThrowHelper.IndexMustBeLessException();
+            }
+            return ref *(_items + index);
+        }
+    }
+
+    public int Capacity
+    {
+        get => _arrayLength;
+        set
+        {
+            if (value < Count) ThrowHelper.ListSmallCapacity();
+
+            if (value != _arrayLength)
+            {
+                if (value > 0)
+                {
+                    var newArray = (T*)NativeMemoryHelper.Alloc((UIntPtr)value, (UIntPtr)Unsafe.SizeOf<T>());
+                    if (Count > 0)
+                        Unsafe.CopyBlockUnaligned(newArray, _items, (uint)(_arrayLength * Unsafe.SizeOf<T>()));
+                    NativeMemoryHelper.Free(_items);
+                    GC.RemoveMemoryPressure(Unsafe.SizeOf<T>() * _arrayLength);
+                    _items = newArray;
+                    _arrayLength = value;
+                }
+                else
+                {
+                    ThrowHelper.ListSmallCapacity();
+                }
+            }
+        }
+    }
+
+    
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public void Add(T value)
+    {
+        var array = _items;
+        var size = Count;
+        if ((uint)size < (uint)_arrayLength)
+        {
+            Count = size + 1;
+            array[size] = value;
+        }
+        else
+        {
+            AddWithResize(value);
+        }
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public void CopyTo(T[] array, int arrayIndex)
+    {
+        throw new NotImplementedException();
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public bool Remove(T item)
+    {
+        var index = IndexOf(item);
+        //Console.WriteLine($"index: {index}");
+        if (index >= 0)
+        {
+            RemoveAt(index);
+            return true;
+        }
+
+        return false;
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public int IndexOf(in T item)
+    {
+        return new Span<T>(_items, Count).IndexOf(item);
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public void RemoveAt(int index)
+    {
+        if ((uint)index >= (uint)Count) ThrowHelper.IndexMustBeLessException();
+        Count--;
+        if (index < Count)
+            Unsafe.CopyBlockUnaligned(_items + index, _items + index + 1, (uint)((Count - index) * Unsafe.SizeOf<T>()));
+    }
+
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public void Clear()
+    {
+        Count = 0;
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public bool Contains(T item)
+    {
+        return IndexOf(item) >= 0;
+    }
+    
+    public void Insert(int index, T item)
+    {
+        // Note that insertions at the end are legal.
+        if ((uint)index > (uint)Count)
+        {
+            ThrowHelper.IndexMustBeLessException();
+        }
+        if (Count == _arrayLength) Grow(Count + 1);
+        if (index < Count)
+        {
+            Unsafe.CopyBlockUnaligned(_items+index+1,_items+index,(uint)(Count-index));
+        }
+        _items[index] = item;
+        Count++;
+    }
+
+    public void AddRange(Span<T> collection)
+    {
+        InsertRange(Count, collection);
+    }
+    
+    public void InsertRange(int index, Span<T> collection)
+    {
+        
+        if ((uint)index > (uint)Count)
+        {
+            ThrowHelper.ListIndexOutOfRange();
+        }
+        
+        int count = collection.Length;
+        if (count > 0)
+        {
+            if (_arrayLength - Count < count)
+            {
+                Grow(Count + count);
+            }
+            if (index < Count)
+            {
+                Unsafe.CopyBlockUnaligned(_items+index+count,_items+index,(uint)(Count-index));
+            }
+            
+            collection.CopyTo(new Span<T>(_items,index));
+            Count += count;
+        }
+        
+    }
+
+    public void RemoveRange(int index, int count)
+    {
+        if (index < 0)
+        {
+            ThrowHelper.ListIndexOutOfRange();
+        }
+
+        if (count < 0)
+        {
+            ThrowHelper.ListIndexOutOfRange();
+        }
+
+        if (Count - index < count)
+            ThrowHelper.ListIndexOutOfRange();
+
+        if (count > 0)
+        {
+            Count -= count;
+            if (index < Count)
+            {
+                Unsafe.CopyBlockUnaligned(_items+index,_items+index+count,(uint)(Count-index));
+            }
+        }
+    }
+    
+
+    public void FillDefaultValue()
+    {
+        for (int i = 0; i < _arrayLength; i++)
+        {
+            _items[i] = default;
+        }
+        Count = _arrayLength;
+    }
+
+    public void ResizeWithDefaultValue(int newSize)
+    {
+        var size = _arrayLength;
+        Capacity = newSize;
+        for (int i = size; i < _arrayLength; i++)
+        {
+            _items[i] = default;
+        }
+    }
+
+    public int Count { get; private set; }
+
+    public bool IsReadOnly => false;
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    private void AddWithResize(in T item)
+    {
+        var size = Count;
+        Grow(size + 1);
+        Count = size + 1;
+        _items[size] = item;
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    private void Grow(int capacity)
+    {
+        Debug.Assert(_arrayLength < capacity);
+
+        var newcapacity = _arrayLength == 0 ? _defaultCapacity : 2 * Count;
+
+        // Allow the list to grow to maximum possible capacity (~2G elements) before encountering overflow.
+        // Note that this check works even when _items.Length overflowed thanks to the (uint) cast
+        if ((uint)newcapacity > 0X7FFFFFC7) newcapacity = 0X7FFFFFC7;
+
+        // If the computed capacity is still less than specified, set to the original argument.
+        // Capacities exceeding Array.MaxLength will be surfaced as OutOfMemoryException by Array.Resize.
+        if (newcapacity < capacity) newcapacity = capacity;
+
+        Capacity = newcapacity;
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public Span<T> WrittenSpan()
+    {
+        return new Span<T>(_items, Count);
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public Span<T> TotalSpan()
+    {
+        return new Span<T>(_items, _arrayLength);
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public void Dispose()
+    {
+        NativeMemoryHelper.Free(_items);
+        GC.RemoveMemoryPressure(_arrayLength * Unsafe.SizeOf<T>());
+    }
+
+
+    IEnumerator<T> IEnumerable<T>.GetEnumerator()
+    {
+        return GetEnumerator();
+    }
+
+    IEnumerator IEnumerable.GetEnumerator()
+    {
+        return GetEnumerator();
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public Enumerator GetEnumerator()
+    {
+        return new Enumerator(self);
+    }
+
+    public override string ToString()
+    {
+        var sb = new StringBuilder();
+        foreach (var item in *self) sb.Append($"{item}  ");
+        return sb.ToString();
+    }
+
+    public struct Enumerator : IEnumerator<T>
+    {
+        object IEnumerator.Current => Current;
+
+        private int CurrentIndex;
+
+        private T CurrentItem;
+
+        private readonly List<T>* Items;
+
+        internal Enumerator(List<T>* items)
+        {
+            Items = items;
+            CurrentIndex = 0;
+            CurrentItem = default;
+        }
+
+        private void Initialize()
+        {
+            CurrentIndex = 0;
+            CurrentItem = default;
+        }
+
+        public bool MoveNext()
+        {
+            if (CurrentIndex == Items->Count) return false;
+
+            CurrentItem = Items->_items[CurrentIndex];
+
+            CurrentIndex++;
+            return true;
+        }
+
+        public void Reset()
+        {
+            Initialize();
+        }
+
+        public T Current => CurrentItem;
+
+        public void Dispose()
+        {
+        }
+    }
+
+    public void OnReturnToPool()
+    {
+        Clear();
+    }
+
+    public void OnGetFromPool()
+    {
+        
+    }
+}
+}
+

+ 11 - 0
Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/List.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: bba344e6402a2f646a3863e12d0858b6
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 8 - 0
Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/MultiMap.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 95b3062e465cb784093095767498d480
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 125 - 0
Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/MultiMap/MultiMap.cs

@@ -0,0 +1,125 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+
+namespace NativeCollection.UnsafeType
+{
+    public unsafe struct MultiMap<T, K> : IEnumerable<MultiMapPair<T, K>>, IDisposable
+    where T : unmanaged, IEquatable<T>, IComparable<T> where K : unmanaged, IEquatable<K>
+{
+    private UnsafeType.SortedSet<MultiMapPair<T, K>>* _sortedSet;
+
+    private NativePool<List<K>>* _listPool;
+
+    public static MultiMap<T, K>* Create(int maxPoolSize)
+    {
+        MultiMap<T, K>* multiMap = (MultiMap<T, K>*)NativeMemoryHelper.Alloc((UIntPtr)Unsafe.SizeOf<MultiMap<T, K>>());
+        multiMap->_sortedSet = UnsafeType.SortedSet<MultiMapPair<T, K>>.Create(maxPoolSize);
+        multiMap->_listPool = NativePool<List<K>>.Create(maxPoolSize);
+        return multiMap;
+    }
+
+    public Span<K> this[T key] {
+        get
+        {
+            var list = new MultiMapPair<T, K>(key);
+            var node = _sortedSet->FindNode(list);
+            if (node!=null)
+            {
+                return node->Item.Value.WrittenSpan();
+            }
+            return Span<K>.Empty;
+        }
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public void Add(T key, K value)
+    {
+        var list = new MultiMapPair<T, K>(key);
+        var node = _sortedSet->FindNode(list);
+        if (node != null)
+        {
+            list = node->Item;
+        }
+        else
+        {
+            list = MultiMapPair<T, K>.Create(key,_listPool);
+            _sortedSet->Add(list);
+        }
+        list.Value.Add(value);
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public bool Remove(T key, K value)
+    {
+        var list = new MultiMapPair<T, K>(key);
+        var node = _sortedSet->FindNode(list);
+
+        if (node == null) return false;
+        list = node->Item;
+        if (!list.Value.Remove(value)) return false;
+
+        if (list.Value.Count == 0) Remove(key);
+
+        return true;
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public bool Remove(T key)
+    {
+        var list = new MultiMapPair<T, K>(key);
+        SortedSet<MultiMapPair<T, K>>.Node* node = _sortedSet->FindNode(list);
+
+        if (node == null) return false;
+        list = node->Item;
+        var sortedSetRemove = _sortedSet->Remove(list);
+        list.Dispose(_listPool);
+        return sortedSetRemove;
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public void Clear()
+    {
+        _sortedSet->Clear();
+    }
+
+    public int Count => _sortedSet->Count;
+    
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    IEnumerator<MultiMapPair<T, K>> IEnumerable<MultiMapPair<T, K>>.GetEnumerator()
+    {
+        return _sortedSet->GetEnumerator();
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    IEnumerator IEnumerable.GetEnumerator()
+    {
+        return _sortedSet->GetEnumerator();
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public UnsafeType.SortedSet<MultiMapPair<T, K>>.Enumerator GetEnumerator()
+    {
+        return new UnsafeType.SortedSet<MultiMapPair<T, K>>.Enumerator(_sortedSet);
+    }
+    
+    public void Dispose()
+    {
+        if (_sortedSet != null)
+        {
+            _sortedSet->Dispose();
+            NativeMemoryHelper.Free(_sortedSet);
+            GC.RemoveMemoryPressure(Unsafe.SizeOf<UnsafeType.SortedSet<MultiMapPair<T, K>>>());
+        }
+
+        if (_listPool!=null)
+        {
+            _listPool->Dispose();
+            NativeMemoryHelper.Free(_listPool);
+            GC.RemoveMemoryPressure(Unsafe.SizeOf<NativePool<List<K>>>());
+        }
+    }
+}
+}
+

+ 11 - 0
Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/MultiMap/MultiMap.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 9c68c2e9cfe59a644bc3730803efc13d
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 62 - 0
Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/MultiMap/MultiMapPair.cs

@@ -0,0 +1,62 @@
+using System;
+using System.Runtime.CompilerServices;
+
+namespace NativeCollection.UnsafeType
+{
+    public unsafe struct MultiMapPair<T, K> : IEquatable<MultiMapPair<T, K>>, IComparable<MultiMapPair<T, K>>
+        where T : unmanaged, IEquatable<T>, IComparable<T> where K : unmanaged, IEquatable<K>
+    {
+        private UnsafeType.List<K>* _value;
+    
+        public T Key { get; private set; }
+    
+        public ref UnsafeType.List<K> Value => ref Unsafe.AsRef<UnsafeType.List<K>>(_value);
+    
+        public MultiMapPair(T key)
+        {
+            Key = key;
+            _value = null;
+        }
+    
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static MultiMapPair<T, K> Create(T key, NativePool<List<K>>* pool)
+        {
+            var pair = new MultiMapPair<T, K>(key);
+            var list = pool->Alloc();
+            if (list==null)
+            {
+                list = List<K>.Create();
+            }
+            pair._value = list;
+            return pair;
+        }
+    
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public bool Equals(MultiMapPair<T, K> other)
+        {
+            return Key.Equals(other.Key);
+        }
+    
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public int CompareTo(MultiMapPair<T, K> other)
+        {
+            return Key.CompareTo(other.Key);
+        }
+    
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public override int GetHashCode()
+        {
+            return Key.GetHashCode();
+        }
+    
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void Dispose(NativePool<List<K>>* pool)
+        {
+            if (_value!=null)
+            {
+                pool->Return(_value);
+            }
+        }
+    }
+}
+

+ 11 - 0
Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/MultiMap/MultiMapPair.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 649c839ac1a5c464d88d2b827cfc03d9
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 70 - 0
Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/NativePool.cs

@@ -0,0 +1,70 @@
+using System;
+using System.Runtime.CompilerServices;
+
+namespace NativeCollection.UnsafeType
+{
+    public interface IPool : IDisposable
+    {
+        public void OnReturnToPool();
+        public void OnGetFromPool();
+    }
+    
+    public unsafe struct NativePool<T> : IDisposable where T: unmanaged,IPool
+    {
+        public int MaxSize { get; private set; }
+        private Stack<IntPtr>* _stack;
+        public static NativePool<T>* Create(int maxPoolSize)
+        {
+            NativePool<T>* pool = (NativePool<T>*)NativeMemoryHelper.Alloc((UIntPtr)Unsafe.SizeOf<NativePool<T>>());
+            pool->_stack = Stack<IntPtr>.Create();
+            pool->MaxSize = maxPoolSize;
+            return pool;
+        }
+    
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public T* Alloc()
+        {
+            if (_stack->TryPop(out var itemPtr))
+            {
+                var item = (T*)itemPtr;
+                item->OnGetFromPool();
+                return item;
+            }
+            return null;
+        }
+    
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void Return(T* ptr)
+        {
+            if (_stack->Count>=MaxSize)
+            {
+                ptr->Dispose();
+                NativeMemoryHelper.Free(ptr);
+                GC.RemoveMemoryPressure(Unsafe.SizeOf<T>());
+                return;
+            }
+            ptr->OnReturnToPool();
+            _stack->Push(new IntPtr(ptr));
+        }
+    
+        public void Clear()
+        {
+            while (_stack->TryPop(out var ptr))
+            {
+                T* item = (T*)ptr;
+                item->Dispose();
+                NativeMemoryHelper.Free(item);
+                GC.RemoveMemoryPressure(Unsafe.SizeOf<T>());
+            }
+        }
+    
+        public void Dispose()
+        {
+            Clear();
+            _stack->Dispose();
+            NativeMemoryHelper.Free(_stack);
+            GC.RemoveMemoryPressure(Unsafe.SizeOf<Stack<T>>());
+        }
+    }
+}
+

+ 11 - 0
Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/NativePool.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 439d2651b8f470f418c65bffa99269fb
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 163 - 0
Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/Queue.cs

@@ -0,0 +1,163 @@
+using System;
+using System.Runtime.CompilerServices;
+
+namespace NativeCollection.UnsafeType
+{
+    public unsafe struct Queue<T> : IDisposable where T : unmanaged
+{
+    private T* _array;
+    private int length;
+
+    private int _head;
+    private int _tail;
+    private int _version;
+
+    public static Queue<T>* Create(int capacity = 10)
+    {
+        if (capacity < 0) throw new ArgumentOutOfRangeException("Capacity<0");
+
+        var queue = (Queue<T>*)NativeMemoryHelper.Alloc((UIntPtr)Unsafe.SizeOf<Queue<T>>());
+        queue->_array = (T*)NativeMemoryHelper.Alloc((UIntPtr)capacity, (UIntPtr)Unsafe.SizeOf<T>());
+        queue->length = capacity;
+        queue->_head = 0;
+        queue->_tail = 0;
+        queue->Count = 0;
+        queue->_version = 0;
+        return queue;
+    }
+
+    public int Count { get; private set; }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public void Clear()
+    {
+        if (Count != 0) Count = 0;
+        _head = 0;
+        _tail = 0;
+        ++_version;
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public void Enqueue(in T item)
+    {
+        if (Count == length)
+            Grow(Count + 1);
+        _array[_tail] = item;
+        MoveNext(ref _tail);
+        ++Count;
+        ++_version;
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public T Dequeue()
+    {
+        var head = _head;
+        var array = _array;
+        if (Count == 0)
+            ThrowHelper.QueueEmptyException();
+
+        var obj = array[head];
+        MoveNext(ref _head);
+        --Count;
+        ++_version;
+        return obj;
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public bool TryDequeue(out T result)
+    {
+        var head = _head;
+        var array = _array;
+        if (Count == 0)
+        {
+            result = default;
+            return false;
+        }
+
+        result = array[head];
+        MoveNext(ref _head);
+        --Count;
+        ++_version;
+        return true;
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public T Peek()
+    {
+        if (Count == 0)
+            ThrowHelper.QueueEmptyException();
+        return _array[_head];
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public bool TryPeek(out T result)
+    {
+        if (Count == 0)
+        {
+            result = default;
+            return false;
+        }
+
+        result = _array[_head];
+        return true;
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    private void Grow(int capacity)
+    {
+        var val1 = 2 * length;
+        if ((uint)val1 > 2147483591U)
+            val1 = 2147483591;
+        var capacity1 = Math.Max(val1, length + 4);
+        if (capacity1 < capacity)
+            capacity1 = capacity;
+        SetCapacity(capacity1);
+    }
+
+    private void SetCapacity(int capacity)
+    {
+        var destinationArray = (T*)NativeMemoryHelper.Alloc((UIntPtr)capacity, (UIntPtr)Unsafe.SizeOf<T>());
+        if (Count > 0)
+        {
+            if (_head < _tail)
+            {
+                Unsafe.CopyBlockUnaligned(destinationArray, _array + _head, (uint)(Count * Unsafe.SizeOf<T>()));
+            }
+            else
+            {
+                Unsafe.CopyBlockUnaligned(destinationArray, _array + _head,
+                    (uint)((length - _head) * Unsafe.SizeOf<T>()));
+                Unsafe.CopyBlockUnaligned(destinationArray + length - _head, _array,
+                    (uint)(_tail * Unsafe.SizeOf<T>()));
+            }
+        }
+
+        NativeMemoryHelper.Free(_array);
+        GC.RemoveMemoryPressure(length * Unsafe.SizeOf<T>());
+        _array = destinationArray;
+        _head = 0;
+        _tail = Count == capacity ? 0 : Count;
+        length = capacity;
+        ++_version;
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    private void MoveNext(ref int index)
+    {
+        var num = index + 1;
+        if (num == length)
+            num = 0;
+        index = num;
+    }
+
+    public void Dispose()
+    {
+        if (_array!=null)
+        {
+            NativeMemoryHelper.Free(_array);
+            GC.RemoveMemoryPressure(length * Unsafe.SizeOf<T>());
+        }
+    }
+}
+}
+

+ 11 - 0
Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/Queue.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 72d098fcb0407df47a71437960937e8b
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 8 - 0
Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/SortedSet.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: dd839f2e7f753f745a43cfc988a39246
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 355 - 0
Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/SortedSet/Node.cs

@@ -0,0 +1,355 @@
+using System;
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace NativeCollection.UnsafeType
+{
+    public unsafe partial struct SortedSet<T>
+{
+    internal enum NodeColor : byte
+    {
+        Black,
+        Red
+    }
+
+    internal enum TreeRotation : byte
+    {
+        Left,
+        LeftRight,
+        Right,
+        RightLeft
+    }
+    internal struct Node : IEquatable<Node>, IPool
+    {
+        public T Item;
+
+        public Node* Self;
+
+        public NodeColor Color;
+
+        public Node* Left;
+
+        public Node* Right;
+
+        public bool IsBlack => Color == NodeColor.Black;
+
+        public bool IsRed => Color == NodeColor.Red;
+
+        public bool Is2Node => IsBlack && IsNullOrBlack(Left) && IsNullOrBlack(Right);
+
+        public bool Is4Node => IsNonNullRed(Left) && IsNonNullRed(Right);
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void ColorBlack()
+        {
+            Color = NodeColor.Black;
+        }
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void ColorRed()
+        {
+            Color = NodeColor.Red;
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static bool IsNonNullBlack(Node* node)
+        {
+            return node != null && node->IsBlack;
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static bool IsNonNullRed(Node* node)
+        {
+            return node != null && node->IsRed;
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static bool IsNullOrBlack(Node* node)
+        {
+            return node == null || node->IsBlack;
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static Node* Create(in T item, NodeColor nodeColor)
+        {
+            var node = (Node*)NativeMemoryHelper.Alloc((UIntPtr)Unsafe.SizeOf<Node>());
+            node->Self = node;
+            node->Item = item;
+            node->Color = nodeColor;
+            node->Left = null;
+            node->Right = null;
+            return node;
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static Node* AllocFromPool(in T item, NodeColor nodeColor, NativePool<Node>* pool)
+        {
+            var node = pool->Alloc();
+            if (node==null)
+            {
+                return Create(item, nodeColor);
+            }
+            node->Self = node;
+            node->Item = item;
+            node->Color = nodeColor;
+            node->Left = null;
+            node->Right = null;
+            return node;
+        }
+
+        public struct NodeSourceTarget : IEquatable<NodeSourceTarget>
+        {
+            public Node* Source;
+            public Node* Target;
+
+            public NodeSourceTarget(Node* source, Node* target)
+            {
+                Source = source;
+                Target = target;
+            }
+
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            public bool Equals(NodeSourceTarget other)
+            {
+                return Source == other.Source && Target == other.Target;
+            }
+
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            public override int GetHashCode()
+            {
+                return HashCode.Combine(unchecked((int)(long)Source), unchecked((int)(long)Target));
+            }
+        }
+
+        public Node* DeepClone(int count)
+        {
+#if DEBUG
+            Debug.Assert(count == GetCount());
+#endif
+            var newRoot = ShallowClone();
+
+            var pendingNodes = UnsafeType.Stack<NodeSourceTarget>.Create(2 * Log2(count) + 2);
+            pendingNodes->Push(new NodeSourceTarget(Self, newRoot));
+
+            while (pendingNodes->TryPop(out var next))
+            {
+                Node* clonedNode;
+
+                var left = next.Source->Left;
+                var right = next.Source->Right;
+                if (left != null)
+                {
+                    clonedNode = left->ShallowClone();
+                    next.Target->Left = clonedNode;
+                    pendingNodes->Push(new NodeSourceTarget(left, clonedNode));
+                }
+
+                if (right != null)
+                {
+                    clonedNode = right->ShallowClone();
+                    next.Target->Right = clonedNode;
+                    pendingNodes->Push(new NodeSourceTarget(right, clonedNode));
+                }
+            }
+
+            pendingNodes->Dispose();
+            NativeMemoryHelper.Free(pendingNodes);
+            GC.RemoveMemoryPressure(Unsafe.SizeOf<UnsafeType.Stack<NodeSourceTarget>>());
+            return newRoot;
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public TreeRotation GetRotation(Node* current, Node* sibling)
+        {
+            Debug.Assert(IsNonNullRed(sibling->Left) || IsNonNullRed(sibling->Right));
+#if DEBUG
+            Debug.Assert(HasChildren(current, sibling));
+#endif
+            var currentIsLeftChild = Left == current;
+            return IsNonNullRed(sibling->Left) ? currentIsLeftChild ? TreeRotation.RightLeft : TreeRotation.Right :
+                currentIsLeftChild ? TreeRotation.Left : TreeRotation.LeftRight;
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public Node* GetSibling(Node* node)
+        {
+            Debug.Assert(node != null);
+            Debug.Assert((node == Left) ^ (node == Right));
+
+            return node == Left ? Right : Left;
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public Node* ShallowClone()
+        {
+            return Create(Item, Color);
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void Split4Node()
+        {
+            Debug.Assert(Left != null);
+            Debug.Assert(Right != null);
+
+            ColorRed();
+            Left->ColorBlack();
+            Right->ColorBlack();
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public Node* Rotate(TreeRotation rotation)
+        {
+            Node* removeRed;
+            switch (rotation)
+            {
+                case TreeRotation.Right:
+                    removeRed = Left == null ? Left : Left->Left;
+                    Debug.Assert(removeRed->IsRed);
+                    removeRed->ColorBlack();
+                    return RotateRight();
+                case TreeRotation.Left:
+                    removeRed = Right == null ? Right : Right->Right!;
+                    Debug.Assert(removeRed->IsRed);
+                    removeRed->ColorBlack();
+                    return RotateLeft();
+                case TreeRotation.RightLeft:
+                    Debug.Assert(Right->Left->IsRed);
+                    return RotateRightLeft();
+                case TreeRotation.LeftRight:
+                    Debug.Assert(Left->Right->IsRed);
+                    return RotateLeftRight();
+                default:
+                    Debug.Fail($"{nameof(rotation)}: {rotation} is not a defined {nameof(TreeRotation)} value.");
+                    return null;
+            }
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public Node* RotateLeft()
+        {
+            var child = Right;
+            Right = child->Left;
+            child->Left = Self;
+            return child;
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public Node* RotateLeftRight()
+        {
+            var child = Left;
+            var grandChild = child->Right!;
+
+            Left = grandChild->Right;
+            grandChild->Right = Self;
+            child->Right = grandChild->Left;
+            grandChild->Left = child;
+            return grandChild;
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public Node* RotateRight()
+        {
+            var child = Left;
+            Left = child->Right;
+            child->Right = Self;
+            return child;
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public Node* RotateRightLeft()
+        {
+            var child = Right;
+            var grandChild = child->Left;
+
+            Right = grandChild->Left;
+            grandChild->Left = Self;
+            child->Left = grandChild->Right;
+            grandChild->Right = child;
+            return grandChild;
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void Merge2Nodes()
+        {
+            Debug.Assert(IsRed);
+            Debug.Assert(Left->Is2Node);
+            Debug.Assert(Right->Is2Node);
+
+            // Combine two 2-nodes into a 4-node.
+            ColorBlack();
+            Left->ColorRed();
+            Right->ColorRed();
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void ReplaceChild(Node* child, Node* newChild)
+        {
+#if DEBUG
+            Debug.Assert(HasChild(child));
+#endif
+
+            if (Left == child)
+                Left = newChild;
+            else
+                Right = newChild;
+        }
+
+
+#if DEBUG
+        private int GetCount()
+        {
+            var value = 1;
+            if (Left != null) value += Left->GetCount();
+
+            if (Right != null) value += Right->GetCount();
+            return value;
+        }
+
+        private bool HasChild(Node* child)
+        {
+            return child == Left || child == Right;
+        }
+
+        private bool HasChildren(Node* child1, Node* child2)
+        {
+            Debug.Assert(child1 != child2);
+
+            return (Left == child1 && Right == child2)
+                   || (Left == child2 && Right == child1);
+        }
+#endif
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public bool Equals(Node other)
+        {
+            return ((Object)Item).Equals(other.Item) && Self == other.Self && Color == other.Color && Left == other.Left &&
+                   Right == other.Right;
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public override int GetHashCode()
+        {
+            return HashCode.Combine(Item, unchecked((int)(long)Self), (int)Color, unchecked((int)(long)Left),
+                unchecked((int)(long)Right));
+        }
+
+        public void Dispose()
+        {
+            
+        }
+
+        public void OnReturnToPool()
+        {
+            
+        }
+
+        public void OnGetFromPool()
+        {
+            
+        }
+    }
+}
+}
+
+
+

+ 11 - 0
Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/SortedSet/Node.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: d94ea1ea18a27b34f8ccb7f5db9533bc
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 703 - 0
Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/SortedSet/SortedSet.cs

@@ -0,0 +1,703 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Numerics;
+using System.Runtime.CompilerServices;
+using System.Text;
+
+namespace NativeCollection.UnsafeType
+{
+    public unsafe partial struct SortedSet<T> : ICollection<T>, IDisposable where T : unmanaged, IEquatable<T>,IComparable<T>
+{
+    private SortedSet<T>* _self;
+    private int _count;
+    private Node* _root;
+    private NativePool<Node>* _nodePool;
+    private NativePool<Stack<IntPtr>>* _stackPool;
+    private int _version;
+    private const int _defaultNodePoolSize = 200;
+    public static SortedSet<T>* Create(int nodePoolSize = _defaultNodePoolSize)
+    {
+        var sortedSet = (SortedSet<T>*)NativeMemoryHelper.Alloc((UIntPtr)Unsafe.SizeOf<SortedSet<T>>());
+        sortedSet->_self = sortedSet;
+        sortedSet->_root = null;
+        sortedSet->_count = 0;
+        sortedSet->_version = 0;
+        sortedSet->_nodePool = NativePool<Node>.Create(nodePoolSize);
+        sortedSet->_stackPool = NativePool<Stack<IntPtr>>.Create(2);
+        return sortedSet;
+    }
+
+    public T? Min => MinInternal;
+
+    internal T? MinInternal
+    {
+        get
+        {
+            if (_root == null) return default;
+
+            var current = _root;
+            while (current->Left != null) current = current->Left;
+
+            return current->Item;
+        }
+    }
+
+    public T? Max => MaxInternal;
+
+    internal T? MaxInternal
+    {
+        get
+        {
+            if (_root == null) return default;
+
+            var current = _root;
+            while (current->Right != null) current = current->Right;
+
+            return current->Item;
+        }
+    }
+
+
+    public int Count
+    {
+        get
+        {
+            VersionCheck(true);
+            return _count;
+        }
+    }
+
+    bool ICollection<T>.IsReadOnly => false;
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public void CopyTo(T[] array, int index)
+    {
+        CopyTo(array, index, Count);
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public bool Remove(T item)
+    {
+        return DoRemove(item);
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    void ICollection<T>.Add(T item)
+    {
+        Add(item);
+    }
+
+    public void Clear()
+    {
+        using var enumerator = GetEnumerator();
+        var nodeCount = 0;
+        do
+        {
+            if (enumerator.CurrentPointer != null)
+            {
+                NativeMemoryHelper.Free(enumerator.CurrentPointer);
+                GC.RemoveMemoryPressure(Unsafe.SizeOf<Node>());
+                nodeCount++;
+            }
+        } while (enumerator.MoveNext());
+
+        if (nodeCount != 0) GC.RemoveMemoryPressure(nodeCount * Unsafe.SizeOf<Node>());
+
+        _root = null;
+        _count = 0;
+        ++_version;
+
+        _nodePool->Clear();
+        _stackPool->Clear();
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public bool Contains(T item)
+    {
+        return FindNode(item) != null;
+    }
+
+    IEnumerator<T> IEnumerable<T>.GetEnumerator()
+    {
+        return GetEnumerator();
+    }
+
+    IEnumerator IEnumerable.GetEnumerator()
+    {
+        return GetEnumerator();
+    }
+
+    public void Dispose()
+    {
+        Clear();
+        if (_nodePool!=null)
+        {
+            _nodePool->Dispose();
+            NativeMemoryHelper.Free(_nodePool);
+            GC.RemoveMemoryPressure(Unsafe.SizeOf<NativePool<Node>>());
+        }
+        if (_stackPool!=null)
+        {
+            _stackPool->Dispose();
+            NativeMemoryHelper.Free(_stackPool);
+            GC.RemoveMemoryPressure(Unsafe.SizeOf<NativePool<Stack<IntPtr>>>());
+        }
+        _version = 0;
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public void CopyTo(T[] array)
+    {
+        CopyTo(array, 0, Count);
+    }
+
+    public void CopyTo(T[] array, int index, int count)
+    {
+        //ArgumentNullException.ThrowIfNull(array);
+
+        if (index < 0) throw new ArgumentOutOfRangeException(nameof(index), index, "ArgumentOutOfRange_NeedNonNegNum");
+
+        if (count < 0) throw new ArgumentOutOfRangeException(nameof(count), "ArgumentOutOfRange_NeedNonNegNum");
+
+        if (count > array.Length - index) throw new ArgumentException("Arg_ArrayPlusOffTooSmall");
+
+        count += index; // Make `count` the upper bound.
+
+        InOrderTreeWalk(node =>
+        {
+            if (index >= count) return false;
+
+            array[index++] = node->Item;
+            return true;
+        });
+    }
+
+    /// <summary>
+    ///     Does an in-order tree walk and calls the delegate for each node.
+    /// </summary>
+    /// <param name="action">
+    ///     The delegate to invoke on each node.
+    ///     If the delegate returns <c>false</c>, the walk is stopped.
+    /// </param>
+    /// <returns><c>true</c> if the entire tree has been walked; otherwise, <c>false</c>.</returns>
+    internal bool InOrderTreeWalk(TreeWalkPredicate action)
+    {
+        if (_root == null) return true;
+
+        // The maximum height of a red-black tree is 2 * log2(n+1).
+        // See page 264 of "Introduction to algorithms" by Thomas H. Cormen
+        // Note: It's not strictly necessary to provide the stack capacity, but we don't
+        // want the stack to unnecessarily allocate arrays as it grows.
+
+        var stack = UnsafeType.Stack<IntPtr>.Create(2 * Log2(Count + 1));
+        var current = _root;
+
+        while (current != null)
+        {
+            stack->Push((IntPtr)current);
+            current = current->Left;
+        }
+
+        while (stack->Count != 0)
+        {
+            current = (Node*)stack->Pop();
+            if (!action(current)) return false;
+
+            var node = current->Right;
+            while (node != null)
+            {
+                stack->Push((IntPtr)node);
+                node = node->Left;
+            }
+        }
+        stack->Dispose();
+        NativeMemoryHelper.Free(stack);
+        GC.RemoveMemoryPressure(Unsafe.SizeOf<UnsafeType.Stack<IntPtr>>());
+        return true;
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    internal void VersionCheck(bool updateCount = false)
+    {
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    internal int TotalCount()
+    {
+        return Count;
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    internal bool IsWithinRange(T item)
+    {
+        return true;
+    }
+
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public bool Add(T item)
+    {
+        return AddIfNotPresent(item);
+    }
+
+    internal bool AddIfNotPresent(in T item)
+    {
+        if (_root == null)
+        {
+            // The tree is empty and this is the first item.
+            _root = Node.AllocFromPool(item, NodeColor.Black,_nodePool);
+            _count = 1;
+            _version++;
+            return true;
+        }
+
+        // Search for a node at bottom to insert the new node.
+        // If we can guarantee the node we found is not a 4-node, it would be easy to do insertion.
+        // We split 4-nodes along the search path.
+        var current = _root;
+        Node* parent = null;
+        Node* grandParent = null;
+        Node* greatGrandParent = null;
+
+        // Even if we don't actually add to the set, we may be altering its structure (by doing rotations and such).
+        // So update `_version` to disable any instances of Enumerator/TreeSubSet from working on it.
+        _version++;
+
+        var order = 0;
+        while (current != null)
+        {
+            order = item.CompareTo(current->Item);
+            if (order == 0)
+            {
+                // We could have changed root node to red during the search process.
+                // We need to set it to black before we return.
+                _root->ColorBlack();
+                return false;
+            }
+
+            // Split a 4-node into two 2-nodes.
+            if (current->Is4Node)
+            {
+                current->Split4Node();
+                // We could have introduced two consecutive red nodes after split. Fix that by rotation.
+                if (Node.IsNonNullRed(parent)) InsertionBalance(current, parent, grandParent, greatGrandParent);
+            }
+
+            greatGrandParent = grandParent;
+            grandParent = parent;
+            parent = current;
+            current = order < 0 ? current->Left : current->Right;
+        }
+
+        Debug.Assert(parent != null);
+        // We're ready to insert the new node.
+        var node = Node.AllocFromPool(item, NodeColor.Red,_nodePool);
+        if (order > 0)
+            parent->Right = node;
+        else
+            parent->Left = node;
+
+        // The new node will be red, so we will need to adjust colors if its parent is also red.
+        if (parent->IsRed) InsertionBalance(node, parent, grandParent, greatGrandParent);
+
+        // The root node is always black.
+        _root->ColorBlack();
+        ++_count;
+        return true;
+    }
+
+    internal bool DoRemove(T item)
+    {
+        if (_root == null) return false;
+
+        // Search for a node and then find its successor.
+        // Then copy the item from the successor to the matching node, and delete the successor.
+        // If a node doesn't have a successor, we can replace it with its left child (if not empty),
+        // or delete the matching node.
+        //
+        // In top-down implementation, it is important to make sure the node to be deleted is not a 2-node.
+        // Following code will make sure the node on the path is not a 2-node.
+
+        // Even if we don't actually remove from the set, we may be altering its structure (by doing rotations
+        // and such). So update our version to disable any enumerators/subsets working on it.
+        _version++;
+
+        var current = _root;
+        Node* parent = null;
+        Node* grandParent = null;
+        Node* match = null;
+        Node* parentOfMatch = null;
+        var foundMatch = false;
+        while (current != null)
+        {
+            if (current->Is2Node)
+            {
+                // Fix up 2-node
+                if (parent == null)
+                {
+                    // `current` is the root. Mark it red.
+                    current->ColorRed();
+                }
+                else
+                {
+                    var sibling = parent->GetSibling(current);
+                    if (sibling->IsRed)
+                    {
+                        // If parent is a 3-node, flip the orientation of the red link.
+                        // We can achieve this by a single rotation.
+                        // This case is converted to one of the other cases below.
+                        Debug.Assert(parent->IsBlack);
+                        if (parent->Right == sibling)
+                            parent->RotateLeft();
+                        else
+                            parent->RotateRight();
+
+                        parent->ColorRed();
+                        sibling->ColorBlack(); // The red parent can't have black children.
+                        // `sibling` becomes the child of `grandParent` or `root` after rotation. Update the link from that node.
+                        ReplaceChildOrRoot(grandParent, parent, sibling);
+                        // `sibling` will become the grandparent of `current`.
+                        grandParent = sibling;
+                        if (parent == match) parentOfMatch = sibling;
+
+                        sibling = parent->GetSibling(current);
+                    }
+
+                    Debug.Assert(Node.IsNonNullBlack(sibling));
+
+                    if (sibling->Is2Node)
+                    {
+                        parent->Merge2Nodes();
+                    }
+                    else
+                    {
+                        // `current` is a 2-node and `sibling` is either a 3-node or a 4-node.
+                        // We can change the color of `current` to red by some rotation.
+                        var newGrandParent = parent->Rotate(parent->GetRotation(current, sibling))!;
+
+                        newGrandParent->Color = parent->Color;
+                        parent->ColorBlack();
+                        current->ColorRed();
+
+                        ReplaceChildOrRoot(grandParent, parent, newGrandParent);
+                        if (parent == match) parentOfMatch = newGrandParent;
+                    }
+                }
+            }
+
+            // We don't need to compare after we find the match.
+            var order = foundMatch ? -1 : item.CompareTo(current->Item);
+            if (order == 0)
+            {
+                // Save the matching node.
+                foundMatch = true;
+                match = current;
+                parentOfMatch = parent;
+            }
+
+            grandParent = parent;
+            parent = current;
+            // If we found a match, continue the search in the right sub-tree.
+            current = order < 0 ? current->Left : current->Right;
+        }
+
+        // Move successor to the matching node position and replace links.
+        if (match != null)
+        {
+            ReplaceNode(match, parentOfMatch!, parent!, grandParent!);
+            --_count;
+            _nodePool->Return(match);
+        }
+
+        if (_root != null) _root->ColorBlack();
+
+
+        return foundMatch;
+    }
+
+    // After calling InsertionBalance, we need to make sure `current` and `parent` are up-to-date.
+    // It doesn't matter if we keep `grandParent` and `greatGrandParent` up-to-date, because we won't
+    // need to split again in the next node.
+    // By the time we need to split again, everything will be correctly set.
+    private void InsertionBalance(Node* current, Node* parent, Node* grandParent, Node* greatGrandParent)
+    {
+        Debug.Assert(parent != null);
+        Debug.Assert(grandParent != null);
+
+        var parentIsOnRight = grandParent->Right == parent;
+        var currentIsOnRight = parent->Right == current;
+
+        Node* newChildOfGreatGrandParent;
+        if (parentIsOnRight == currentIsOnRight)
+        {
+            // Same orientation, single rotation
+            newChildOfGreatGrandParent = currentIsOnRight ? grandParent->RotateLeft() : grandParent->RotateRight();
+        }
+        else
+        {
+            // Different orientation, double rotation
+            newChildOfGreatGrandParent =
+                currentIsOnRight ? grandParent->RotateLeftRight() : grandParent->RotateRightLeft();
+            // Current node now becomes the child of `greatGrandParent`
+            parent = greatGrandParent;
+        }
+
+        // `grandParent` will become a child of either `parent` of `current`.
+        grandParent->ColorRed();
+        newChildOfGreatGrandParent->ColorBlack();
+
+        ReplaceChildOrRoot(greatGrandParent, grandParent, newChildOfGreatGrandParent);
+    }
+
+    /// <summary>
+    ///     Replaces the child of a parent node, or replaces the root if the parent is <c>null</c>.
+    /// </summary>
+    /// <param name="parent">The (possibly <c>null</c>) parent.</param>
+    /// <param name="child">The child node to replace.</param>
+    /// <param name="newChild">The node to replace <paramref name="child" /> with.</param>
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    private void ReplaceChildOrRoot(Node* parent, Node* child, Node* newChild)
+    {
+        if (parent != null)
+            parent->ReplaceChild(child, newChild);
+        else
+            _root = newChild;
+    }
+
+    /// <summary>
+    ///     Replaces the matching node with its successor.
+    /// </summary>
+    private void ReplaceNode(Node* match, Node* parentOfMatch, Node* successor, Node* parentOfSuccessor)
+    {
+        Debug.Assert(match != null);
+
+        if (successor == match)
+        {
+            // This node has no successor. This can only happen if the right child of the match is null.
+            Debug.Assert(match->Right == null);
+            successor = match->Left!;
+        }
+        else
+        {
+            Debug.Assert(parentOfSuccessor != null);
+            Debug.Assert(successor->Left == null);
+            Debug.Assert((successor->Right == null && successor->IsRed) ||
+                         (successor->Right!->IsRed && successor->IsBlack));
+
+            if (successor->Right != null) successor->Right->ColorBlack();
+
+            if (parentOfSuccessor != match)
+            {
+                // Detach the successor from its parent and set its right child.
+                parentOfSuccessor->Left = successor->Right;
+                successor->Right = match->Right;
+            }
+
+            successor->Left = match->Left;
+        }
+
+        if (successor != null) successor->Color = match->Color;
+
+        ReplaceChildOrRoot(parentOfMatch, match, successor!);
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    internal Node* FindNode(T item)
+    {
+        var current = _root;
+        while (current != null)
+        {
+            var order = item.CompareTo(current->Item);
+            if (order == 0) return current;
+
+            current = order < 0 ? current->Left : current->Right;
+        }
+
+        return null;
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    internal void UpdateVersion()
+    {
+        ++_version;
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    private static int Log2(int value)
+    {
+#if NET6_0_OR_GREATER
+        return BitOperations.Log2((uint)value);
+#else
+        int num = 0;
+        for (; value > 0; value >>= 1)
+            ++num;
+        return num;
+#endif
+    }
+
+    
+    
+    public Enumerator GetEnumerator()
+    {
+        return new Enumerator(_self);
+    }
+
+    internal delegate bool TreeWalkPredicate(Node* node);
+
+    public struct Enumerator : IEnumerator<T>
+    {
+        private readonly SortedSet<T>* _tree;
+        private readonly int _version;
+
+        private readonly UnsafeType.Stack<IntPtr>* _stack;
+        private readonly bool _reverse;
+
+        internal Enumerator(SortedSet<T>* set)
+            : this(set, false)
+        {
+        }
+
+        internal Enumerator(SortedSet<T>* set, bool reverse)
+        {
+            _tree = set;
+            set->VersionCheck();
+            _version = set->_version;
+
+            // 2 log(n + 1) is the maximum height.
+
+            _stack = set->_stackPool->Alloc();
+            if (_stack==null)
+            {
+                _stack = UnsafeType.Stack<IntPtr>.Create(2 * Log2(set->TotalCount() + 1));
+            }
+            CurrentPointer = null;
+            _reverse = reverse;
+            Initialize();
+            
+        }
+
+        private void Initialize()
+        {
+            CurrentPointer = null;
+            var node = _tree->_root;
+            while (node != null)
+            {
+                var next = _reverse ? node->Right : node->Left;
+                var other = _reverse ? node->Left : node->Right;
+                if (_tree->IsWithinRange(node->Item))
+                {
+                    _stack->Push((IntPtr)node);
+                    node = next;
+                }
+                else if (next == null || !_tree->IsWithinRange(next->Item))
+                {
+                    node = other;
+                }
+                else
+                {
+                    node = next;
+                }
+            }
+        }
+
+        public bool MoveNext()
+        {
+            // Make sure that the underlying subset has not been changed since
+            //_tree->VersionCheck();
+
+            if (_version != _tree->_version)
+            {
+                ThrowHelper.SortedSetVersionChanged();
+            }
+
+            if (_stack->Count == 0)
+            {
+                CurrentPointer = null;
+                return false;
+            }
+
+            CurrentPointer = (Node*)_stack->Pop();
+            var node = _reverse ? CurrentPointer->Left : CurrentPointer->Right;
+            while (node != null)
+            {
+                var next = _reverse ? node->Right : node->Left;
+                var other = _reverse ? node->Left : node->Right;
+                if (_tree->IsWithinRange(node->Item))
+                {
+                    _stack->Push((IntPtr)node);
+                    node = next;
+                }
+                else if (other == null || !_tree->IsWithinRange(other->Item))
+                {
+                    node = next;
+                }
+                else
+                {
+                    node = other;
+                }
+            }
+
+            return true;
+        }
+
+
+        public void Dispose()
+        {
+            //Console.WriteLine("Enumerator Dispose");
+            // _stack->Dispose();
+            //
+            // NativeMemoryHelper.Free(_stack);
+            // GC.RemoveMemoryPressure(Unsafe.SizeOf<NativeCollection.Stack<IntPtr>>());
+            _tree->_stackPool->Return(_stack);
+        }
+
+        public T Current
+        {
+            get
+            {
+                if (CurrentPointer != null) return CurrentPointer->Item;
+                return default!; // Should only happen when accessing Current is undefined behavior
+            }
+        }
+
+        internal Node* CurrentPointer { get; private set; }
+
+        internal bool NotStartedOrEnded => CurrentPointer == null;
+
+        internal void Reset()
+        {
+            if (_version != _tree->_version) throw new InvalidOperationException("_version != _tree.version");
+
+            _stack->Clear();
+            Initialize();
+        }
+
+        object IEnumerator.Current
+        {
+            get
+            {
+                if (CurrentPointer == null) throw new InvalidOperationException("_current == null");
+
+                return CurrentPointer->Item;
+            }
+        }
+
+        void IEnumerator.Reset()
+        {
+            Reset();
+        }
+    }
+
+    public override string ToString()
+    {
+        var sb = new StringBuilder();
+        foreach (var value in this) sb.Append($"{value} ");
+
+        return sb.ToString();
+    }
+}
+}
+
+

+ 11 - 0
Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/SortedSet/SortedSet.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 868c74ea9b88a1c4ebce17ca82136935
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 121 - 0
Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/Stack.cs

@@ -0,0 +1,121 @@
+using System;
+using System.Runtime.CompilerServices;
+
+namespace NativeCollection.UnsafeType
+{
+    public unsafe struct Stack<T> : IDisposable, IPool where T : unmanaged
+{
+    private T* _array;
+    private int _version;
+    private const int _defaultCapacity = 10;
+    internal int ArrayLength { get; private set; }
+
+    public static Stack<T>* Create(int initialCapacity = _defaultCapacity)
+    {
+        if (initialCapacity < 0) ThrowHelper.StackInitialCapacityException();
+
+        var stack = (Stack<T>*)NativeMemoryHelper.Alloc((UIntPtr)System.Runtime.CompilerServices.Unsafe.SizeOf<Stack<T>>());
+        GC.AddMemoryPressure(System.Runtime.CompilerServices.Unsafe.SizeOf<Stack<T>>());
+
+        if (initialCapacity < _defaultCapacity)
+            initialCapacity = _defaultCapacity; // Simplify doubling logic in Push.
+
+        stack->_array = (T*)NativeMemoryHelper.Alloc((UIntPtr)initialCapacity, (UIntPtr)System.Runtime.CompilerServices.Unsafe.SizeOf<T>());
+        GC.AddMemoryPressure(initialCapacity * System.Runtime.CompilerServices.Unsafe.SizeOf<T>());
+        stack->ArrayLength = initialCapacity;
+        stack->Count = 0;
+        stack->_version = 0;
+        return stack;
+    }
+
+    public int Count { get; private set; }
+
+
+    public void Clear()
+    {
+        Count = 0;
+        _version++;
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public bool Contains(in T obj)
+    {
+        var count = Count;
+        while (count-- > 0)
+            if (obj.Equals(_array[count]))
+                return true;
+        return false;
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public T Peak()
+    {
+        if (Count == 0) ThrowHelper.StackEmptyException();
+        return _array[Count - 1];
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public T Pop()
+    {
+        if (Count == 0)
+            ThrowHelper.StackEmptyException();
+
+        _version++;
+        var obj = _array[--Count];
+        _array[Count] = default;
+        return obj;
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public bool TryPop(out T result)
+    {
+        var index = Count - 1;
+        var array = _array;
+        if ((uint)index >= (uint)ArrayLength)
+        {
+            result = default;
+            return false;
+        }
+
+        ++_version;
+        Count = index;
+        result = array[index];
+        return true;
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public void Push(in T obj)
+    {
+        if (Count == ArrayLength)
+        {
+            var newArray = (T*)NativeMemoryHelper.Alloc((UIntPtr)(ArrayLength * 2), (UIntPtr)System.Runtime.CompilerServices.Unsafe.SizeOf<T>());
+            System.Runtime.CompilerServices.Unsafe.CopyBlockUnaligned(newArray, _array, (uint)(Count * System.Runtime.CompilerServices.Unsafe.SizeOf<T>()));
+            NativeMemoryHelper.Free(_array);
+            GC.RemoveMemoryPressure(ArrayLength * System.Runtime.CompilerServices.Unsafe.SizeOf<T>());
+            _array = newArray;
+            ArrayLength = ArrayLength * 2;
+        }
+
+        _array[Count++] = obj;
+        _version++;
+    }
+
+    public void Dispose()
+    {
+        NativeMemoryHelper.Free(_array);
+        GC.RemoveMemoryPressure(ArrayLength * System.Runtime.CompilerServices.Unsafe.SizeOf<T>());
+    }
+
+    public void OnReturnToPool()
+    {
+        Clear();
+    }
+
+    public void OnGetFromPool()
+    {
+        
+    }
+}
+}
+
+

+ 11 - 0
Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/Stack.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 15ffb668c548c3046acce73c65bead49
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 3 - 3
Unity/Packages/manifest.json

@@ -2,10 +2,10 @@
   "dependencies": {
     "com.code-philosophy.hybridclr": "https://gitee.com/focus-creative-games/hybridclr_unity.git",
     "com.cysharp.memorypack": "https://github.com/Cysharp/MemoryPack.git?path=src/MemoryPack.Unity/Assets/Plugins/MemoryPack",
-    "com.unity.ide.rider": "3.0.21",
-    "com.unity.ide.visualstudio": "2.0.17",
+    "com.unity.ide.rider": "3.0.24",
+    "com.unity.ide.visualstudio": "2.0.18",
     "com.unity.ide.vscode": "1.2.5",
-    "com.unity.render-pipelines.universal": "12.1.8",
+    "com.unity.render-pipelines.universal": "12.1.12",
     "com.unity.textmeshpro": "3.0.6",
     "com.unity.timeline": "1.7.1",
     "com.unity.ugui": "1.0.0",

+ 11 - 11
Unity/Packages/packages-lock.json

@@ -15,7 +15,7 @@
       "hash": "09eb5f1535d0d01dee98c84fa110c21a436bd896"
     },
     "com.unity.burst": {
-      "version": "1.8.2",
+      "version": "1.8.4",
       "depth": 1,
       "source": "registry",
       "dependencies": {
@@ -31,7 +31,7 @@
       "url": "https://packages.unity.com"
     },
     "com.unity.ide.rider": {
-      "version": "3.0.21",
+      "version": "3.0.24",
       "depth": 0,
       "source": "registry",
       "dependencies": {
@@ -40,7 +40,7 @@
       "url": "https://packages.unity.com"
     },
     "com.unity.ide.visualstudio": {
-      "version": "2.0.17",
+      "version": "2.0.18",
       "depth": 0,
       "source": "registry",
       "dependencies": {
@@ -63,7 +63,7 @@
       "url": "https://packages.unity.com"
     },
     "com.unity.render-pipelines.core": {
-      "version": "12.1.8",
+      "version": "12.1.12",
       "depth": 1,
       "source": "builtin",
       "dependencies": {
@@ -73,14 +73,14 @@
       }
     },
     "com.unity.render-pipelines.universal": {
-      "version": "12.1.8",
+      "version": "12.1.12",
       "depth": 0,
       "source": "builtin",
       "dependencies": {
         "com.unity.mathematics": "1.2.1",
-        "com.unity.burst": "1.8.2",
-        "com.unity.render-pipelines.core": "12.1.8",
-        "com.unity.shadergraph": "12.1.8"
+        "com.unity.burst": "1.8.4",
+        "com.unity.render-pipelines.core": "12.1.12",
+        "com.unity.shadergraph": "12.1.12"
       }
     },
     "com.unity.searcher": {
@@ -91,16 +91,16 @@
       "url": "https://packages.unity.com"
     },
     "com.unity.shadergraph": {
-      "version": "12.1.8",
+      "version": "12.1.12",
       "depth": 1,
       "source": "builtin",
       "dependencies": {
-        "com.unity.render-pipelines.core": "12.1.8",
+        "com.unity.render-pipelines.core": "12.1.12",
         "com.unity.searcher": "4.9.1"
       }
     },
     "com.unity.test-framework": {
-      "version": "1.1.31",
+      "version": "1.1.33",
       "depth": 1,
       "source": "registry",
       "dependencies": {

+ 2 - 2
Unity/ProjectSettings/ProjectVersion.txt

@@ -1,2 +1,2 @@
-m_EditorVersion: 2021.3.16f1
-m_EditorVersionWithRevision: 2021.3.16f1 (4016570cf34f)
+m_EditorVersion: 2021.3.29f1
+m_EditorVersionWithRevision: 2021.3.29f1 (204d6dc9ae1c)