using System; using System.Collections.Generic; using System.Linq; using System.Threading; using UnityEngine; public class Loom : MonoBehaviour { public const int maxThreads = 8; private static int numThreads; private static bool initialized; private static Loom current; private readonly List actions = new List(); private readonly List delayed = new List(); private readonly List currentDelayed = new List(); private readonly List currentActions = new List(); public static Loom Current { get { Initialize(); return current; } } void Start() { } void Update() { lock (actions) { currentActions.Clear(); currentActions.AddRange(actions); actions.Clear(); } foreach (var a in currentActions) { a(); } lock (delayed) { currentDelayed.Clear(); currentDelayed.AddRange(delayed.Where(d => d.time <= Time.time)); foreach (var item in currentDelayed) delayed.Remove(item); } foreach (var delayed in currentDelayed) { delayed.action(); } } /// /// 初始化 /// public static void Initialize() { if (!initialized) { if (!Application.isPlaying) return; initialized = true; GameObject g = new GameObject("Loom"); // 永不销毁 DontDestroyOnLoad(g); current = g.AddComponent(); } } public static void QueueOnMainThread(Action action) { QueueOnMainThread(action, 0f); } public static void QueueOnMainThread(Action action, float time) { if (time != 0) { if (Current != null) { lock (Current.delayed) { Current.delayed.Add(new DelayedQueueItem { time = Time.time + time, action = action }); } } } else { if (Current != null) { lock (Current.actions) { Current.actions.Add(action); } } } } public static Thread RunAsync(Action a) { Initialize(); while (numThreads >= maxThreads) { Thread.Sleep(1); } Interlocked.Increment(ref numThreads); ThreadPool.QueueUserWorkItem(RunAction, a); return null; } private static void RunAction(object action) { try { ((Action)action)(); } catch { } finally { Interlocked.Decrement(ref numThreads); } } void OnDisable() { if (current == this) { current = null; } } public struct DelayedQueueItem { public float time; public Action action; } }