ObjectPool.cs 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Reflection;
  6. using System.Text;
  7. using ETModel;
  8. using UnityEngine;
  9. namespace ETHotfix
  10. {
  11. public class ComponentQueue: IDisposable
  12. {
  13. public long Id;
  14. #if !SERVER
  15. public static GameObject Global { get; } = GameObject.Find("/Global");
  16. public GameObject ViewGO { get; set; }
  17. #endif
  18. public string TypeName { get; }
  19. private readonly Queue<Entity> queue = new Queue<Entity>();
  20. public ComponentQueue(string typeName)
  21. {
  22. this.Id = IdGenerater.GenerateId();
  23. this.TypeName = typeName;
  24. #if !SERVER
  25. this.ViewGO = new GameObject();
  26. this.ViewGO.name = this.GetType().Name;
  27. this.ViewGO.layer = LayerNames.GetLayerInt(LayerNames.HIDDEN);
  28. this.ViewGO.transform.SetParent(Global.transform, false);
  29. this.ViewGO.AddComponent<ComponentView>().Component = this;
  30. #endif
  31. }
  32. public void Enqueue(Entity entity)
  33. {
  34. this.queue.Enqueue(entity);
  35. }
  36. public Entity Dequeue()
  37. {
  38. return this.queue.Dequeue();
  39. }
  40. public Entity Peek()
  41. {
  42. return this.queue.Peek();
  43. }
  44. public Queue<Entity> Queue
  45. {
  46. get
  47. {
  48. return this.queue;
  49. }
  50. }
  51. public int Count
  52. {
  53. get
  54. {
  55. return this.queue.Count;
  56. }
  57. }
  58. public void Dispose()
  59. {
  60. while (this.queue.Count > 0)
  61. {
  62. Entity component = this.queue.Dequeue();
  63. component.Dispose();
  64. }
  65. }
  66. }
  67. public class ObjectPool: IDisposable
  68. {
  69. #if !SERVER
  70. public static GameObject Global { get; } = GameObject.Find("/Global");
  71. public GameObject ViewGO { get; set; }
  72. #endif
  73. public string Name { get; set; }
  74. private readonly Dictionary<Type, ComponentQueue> dictionary = new Dictionary<Type, ComponentQueue>();
  75. public ObjectPool()
  76. {
  77. #if !SERVER
  78. this.ViewGO = new GameObject();
  79. this.ViewGO.name = this.GetType().Name;
  80. this.ViewGO.layer = LayerNames.GetLayerInt(LayerNames.HIDDEN);
  81. this.ViewGO.transform.SetParent(Global.transform, false);
  82. this.ViewGO.AddComponent<ComponentView>().Component = this;
  83. #endif
  84. }
  85. public Entity Fetch(Type type)
  86. {
  87. Entity obj;
  88. if (!this.dictionary.TryGetValue(type, out ComponentQueue queue))
  89. {
  90. obj = (Entity)Activator.CreateInstance(type);
  91. }
  92. else if (queue.Count == 0)
  93. {
  94. obj = (Entity)Activator.CreateInstance(type);
  95. }
  96. else
  97. {
  98. obj = queue.Dequeue();
  99. }
  100. obj.IsFromPool = true;
  101. return obj;
  102. }
  103. public T Fetch<T>() where T: Entity
  104. {
  105. T t = (T) this.Fetch(typeof(T));
  106. return t;
  107. }
  108. public void Recycle(Entity obj)
  109. {
  110. Type type = obj.GetType();
  111. ComponentQueue queue;
  112. if (!this.dictionary.TryGetValue(type, out queue))
  113. {
  114. queue = new ComponentQueue(type.Name);
  115. #if !SERVER
  116. if (queue.ViewGO != null)
  117. {
  118. queue.ViewGO.transform.SetParent(this.ViewGO.transform);
  119. queue.ViewGO.name = $"{type.Name}s";
  120. }
  121. #endif
  122. this.dictionary.Add(type, queue);
  123. }
  124. #if !SERVER
  125. if (obj.ViewGO != null)
  126. {
  127. obj.ViewGO.transform.SetParent(queue.ViewGO.transform);
  128. }
  129. #endif
  130. obj.Id = 0;
  131. queue.Enqueue(obj);
  132. }
  133. public void Dispose()
  134. {
  135. foreach (var kv in this.dictionary)
  136. {
  137. kv.Value.Dispose();
  138. }
  139. this.dictionary.Clear();
  140. }
  141. public override string ToString()
  142. {
  143. StringBuilder sb = new StringBuilder();
  144. Dictionary<Type, int> typeCount = new Dictionary<Type, int>();
  145. foreach (var kv in this.dictionary)
  146. {
  147. typeCount[kv.Key] = kv.Value.Count;
  148. }
  149. IOrderedEnumerable<KeyValuePair<Type, int>> orderByDescending = typeCount.OrderByDescending(s => s.Value);
  150. sb.AppendLine("ObjectPool Count: ");
  151. foreach (var kv in orderByDescending)
  152. {
  153. if (kv.Value == 1)
  154. {
  155. continue;
  156. }
  157. sb.AppendLine($"\t{kv.Key.Name}: {kv.Value}");
  158. }
  159. MultiMapSet<string, string> dict = Check();
  160. sb.Append("not reset field:\n");
  161. foreach (KeyValuePair<string,HashSet<string>> pair in dict.GetDictionary())
  162. {
  163. sb.Append(pair.Key + ": ");
  164. foreach (string value in pair.Value)
  165. {
  166. sb.Append(value + ", ");
  167. }
  168. sb.Append("\n");
  169. }
  170. return sb.ToString();
  171. }
  172. public void LogErrorCheckResult()
  173. {
  174. MultiMapSet<string, string> dict = Check();
  175. if (dict.Count == 0)
  176. {
  177. return;
  178. }
  179. StringBuilder sb = new StringBuilder();
  180. sb.Append("not reset field:\n");
  181. foreach (KeyValuePair<string,HashSet<string>> pair in dict.GetDictionary())
  182. {
  183. sb.Append(pair.Key + ": ");
  184. foreach (string value in pair.Value)
  185. {
  186. sb.Append(value + ", ");
  187. }
  188. sb.Append("\n");
  189. }
  190. Log.Error(sb.ToString());
  191. }
  192. public MultiMapSet<string, string> Check()
  193. {
  194. MultiMapSet<string, string> dict = new MultiMapSet<string, string>();
  195. foreach (ComponentQueue queue in this.dictionary.Values)
  196. {
  197. foreach (Entity entity in queue.Queue)
  198. {
  199. Type type = entity.GetType();
  200. #if SERVER
  201. if (type.IsSubclassOf(typeof (LogDefine)))
  202. {
  203. continue;
  204. }
  205. #endif
  206. FieldInfo[] fieldInfos = type.GetFields();
  207. foreach (FieldInfo fieldInfo in fieldInfos)
  208. {
  209. if (fieldInfo.IsLiteral)
  210. {
  211. continue;
  212. }
  213. if (fieldInfo.GetCustomAttributes(typeof (NoMemoryCheck)).Count() > 0)
  214. {
  215. continue;
  216. }
  217. Type fieldType = fieldInfo.FieldType;
  218. if (fieldType == typeof (int))
  219. {
  220. if ((int) fieldInfo.GetValue(entity) != 0)
  221. {
  222. dict.Add(type.Name, fieldInfo.Name);
  223. }
  224. continue;
  225. }
  226. if (fieldType == typeof (uint))
  227. {
  228. if ((uint) fieldInfo.GetValue(entity) != 0)
  229. {
  230. dict.Add(type.Name, fieldInfo.Name);
  231. }
  232. continue;
  233. }
  234. if (fieldType == typeof (long))
  235. {
  236. if ((long) fieldInfo.GetValue(entity) != 0)
  237. {
  238. dict.Add(type.Name, fieldInfo.Name);
  239. }
  240. continue;
  241. }
  242. if (fieldType == typeof (ulong))
  243. {
  244. if ((ulong) fieldInfo.GetValue(entity) != 0)
  245. {
  246. dict.Add(type.Name, fieldInfo.Name);
  247. }
  248. continue;
  249. }
  250. if (fieldType == typeof (short))
  251. {
  252. if ((short) fieldInfo.GetValue(entity) != 0)
  253. {
  254. dict.Add(type.Name, fieldInfo.Name);
  255. }
  256. continue;
  257. }
  258. if (fieldType == typeof (ushort))
  259. {
  260. if ((ushort) fieldInfo.GetValue(entity) != 0)
  261. {
  262. dict.Add(type.Name, fieldInfo.Name);
  263. }
  264. continue;
  265. }
  266. if (fieldType == typeof (float))
  267. {
  268. if (Math.Abs((float)fieldInfo.GetValue(entity)) > 0.0001)
  269. {
  270. dict.Add(type.Name, fieldInfo.Name);
  271. }
  272. continue;
  273. }
  274. if (fieldType == typeof (double))
  275. {
  276. if (Math.Abs((double)fieldInfo.GetValue(entity)) > 0.0001)
  277. {
  278. dict.Add(type.Name, fieldInfo.Name);
  279. }
  280. continue;
  281. }
  282. if (fieldType == typeof (bool))
  283. {
  284. if ((bool) fieldInfo.GetValue(entity) != false)
  285. {
  286. dict.Add(type.Name, fieldInfo.Name);
  287. }
  288. continue;
  289. }
  290. if (typeof(ICollection).IsAssignableFrom(fieldType))
  291. {
  292. object fieldValue = fieldInfo.GetValue(entity);
  293. if (fieldValue == null)
  294. {
  295. continue;
  296. }
  297. if (((ICollection)fieldValue).Count != 0)
  298. {
  299. dict.Add(type.Name, fieldInfo.Name);
  300. }
  301. continue;
  302. }
  303. PropertyInfo propertyInfo = fieldType.GetProperty("Count");
  304. if (propertyInfo != null)
  305. {
  306. if ((int) propertyInfo.GetValue(fieldInfo.GetValue(entity)) != 0)
  307. {
  308. dict.Add(type.Name, fieldInfo.Name);
  309. }
  310. continue;
  311. }
  312. if (fieldType.IsClass)
  313. {
  314. if (fieldInfo.GetValue(entity) != null)
  315. {
  316. dict.Add(type.Name, fieldInfo.Name);
  317. }
  318. continue;
  319. }
  320. }
  321. }
  322. }
  323. return dict;
  324. }
  325. }
  326. }