Loom.cs 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Threading;
  5. using UnityEngine;
  6. public class Loom : MonoBehaviour {
  7. #region 公共字段
  8. ///
  9. /// 最大线程数,静态公共字段
  10. ///
  11. public static int maxThreads = 8;
  12. #endregion
  13. #region 私有字段
  14. ///
  15. /// 当前线程数,静态私有字段
  16. ///
  17. private static int numThreads;
  18. ///
  19. /// 单例模式
  20. ///
  21. private static Loom _current;
  22. private int _count;
  23. ///
  24. /// 是否已初始化
  25. ///
  26. private static bool initialized;
  27. private List<Action> _actions;
  28. private List<DelayedQueueItem> _delayed;
  29. private List<DelayedQueueItem> _currentDelayed;
  30. ///
  31. /// 当前行为列表
  32. ///
  33. private List<Action> _currentActions;
  34. #endregion
  35. #region 公有属性
  36. ///
  37. /// 得到当前Loom对象的单例属性
  38. ///
  39. public static Loom Current {
  40. get {
  41. Initialize();
  42. return _current;
  43. }
  44. }
  45. #endregion
  46. #region Unity3d API
  47. void Awake() {
  48. _current = this;
  49. initialized = true;
  50. _actions = new List<Action>();
  51. _delayed = new List<DelayedQueueItem>();
  52. _currentDelayed = new List<DelayedQueueItem>();
  53. _currentActions = new List<Action>();
  54. }
  55. void Update() {
  56. lock (_actions) {
  57. _currentActions.Clear();
  58. _currentActions.AddRange(_actions);
  59. _actions.Clear();
  60. }
  61. foreach (Action a in _currentActions) {
  62. a();
  63. }
  64. lock (_delayed) {
  65. _currentDelayed.Clear();
  66. _currentDelayed.AddRange(_delayed.Where(d => d.time <= Time.time));
  67. foreach (var item in _currentDelayed)
  68. _delayed.Remove(item);
  69. }
  70. foreach (var delayed in _currentDelayed) {
  71. delayed.action();
  72. }
  73. }
  74. void OnDisable() {
  75. if (_current == this) {
  76. _current = null;
  77. }
  78. }
  79. private void OnDestroy() {
  80. initialized = false;
  81. }
  82. #endregion Unity3d API
  83. #region Static Methods
  84. ///
  85. /// 初始化,造一个新的游戏物体Loom,并加一个Loom脚本
  86. ///
  87. private static void Initialize() {
  88. if (!initialized) {
  89. if (!Application.isPlaying)
  90. return;
  91. initialized = true;
  92. GameObject g = new GameObject("Loom");
  93. DontDestroyOnLoad(g);
  94. _current = g.AddComponent<Loom>();
  95. }
  96. }
  97. ///
  98. /// 延时队列项
  99. ///
  100. public struct DelayedQueueItem {
  101. public float time;
  102. public Action action;
  103. }
  104. ///
  105. /// 在主线程上运行的代码
  106. ///
  107. public static void QueueOnMainThread(Action action) {
  108. QueueOnMainThread(action, 0f);
  109. }
  110. ///
  111. /// 在主线程上运行的代码, 第2个参数为延迟几秒执行, 依赖Time.time执行
  112. ///
  113. public static void QueueOnMainThread(Action action, float time) {
  114. if (time != 0) {
  115. lock (Current._delayed) {
  116. // 增加Time.time的值给time达到延时的效果
  117. Current._delayed.Add(new DelayedQueueItem { time = Time.time + time, action = action });
  118. }
  119. } else {
  120. if (Current != null && Current._actions != null) {
  121. lock (Current._actions) {
  122. Current._actions.Add(action);
  123. }
  124. }
  125. }
  126. }
  127. ///
  128. /// 在新线程上运行的代码
  129. ///
  130. public static Thread RunAsync(Action a) {
  131. Initialize();
  132. while (numThreads >= maxThreads) {
  133. Thread.Sleep(1);
  134. }
  135. Interlocked.Increment(ref numThreads);
  136. ThreadPool.QueueUserWorkItem(RunAction, a);
  137. return null;
  138. }
  139. private static void RunAction(object action) {
  140. try {
  141. ((Action)action)();
  142. } catch (Exception e) {
  143. Debug.Log(e.Message);
  144. Debug.Log(e.Source);
  145. } finally {
  146. Interlocked.Decrement(ref numThreads);
  147. }
  148. }
  149. #endregion of Static Methods
  150. }