Unity main thread and subthread jump call (1), unity jump
Except for some basic data types, almost all APIs of Unity cannot be called in non-unity threads. If there is a time-consuming operation in the project, unity may be suspended ". If this operation has nothing to do with unity, we can put this time-consuming operation in the Child thread to run it to prevent the unity from falsely Improving the performance, as shown in the following pseudocode
Function {// This Function reads and writes a large number of files. LoadLocalFile (); // This Function is the unity Function UnityFunction ();}
Ensure that LoadLocalFile () is not "suspended ". How can this problem be solved? You just need to put the Function in multiple threads and the UnityFunction () will return to the main thread.
Loom is used to extract a script.
1 using UnityEngine; 2 using System.Collections; 3 using System.Collections.Generic; 4 using System; 5 using System.Threading; 6 using System.Linq; 7 8 public class Loom :MonoBehaviour 9 { 10 public static int maxThreads = 8; 11 static int numThreads; 12 13 private static Loom _current; 14 //private int _count; 15 public static Loom Current 16 { 17 get 18 { 19 Initialize(); 20 return _current; 21 } 22 } 23 24 void Awake() 25 { 26 _current = this; 27 initialized = true; 28 } 29 30 static bool initialized; 31 32 public static void Initialize() 33 { 34 if (!initialized) 35 { 36 37 if (!Application.isPlaying) 38 return; 39 initialized = true; 40 var g = new GameObject("Loom"); 41 _current = g.AddComponent<Loom>(); 42 #if !ARTIST_BUILD 43 UnityEngine.Object.DontDestroyOnLoad(g); 44 #endif 45 } 46 47 } 48 public struct NoDelayedQueueItem 49 { 50 public Action<object> action; 51 public object param; 52 } 53 54 private List<NoDelayedQueueItem> _actions = new List<NoDelayedQueueItem>(); 55 public struct DelayedQueueItem 56 { 57 public float time; 58 public Action<object> action; 59 public object param; 60 } 61 private List<DelayedQueueItem> _delayed = new List<DelayedQueueItem>(); 62 63 List<DelayedQueueItem> _currentDelayed = new List<DelayedQueueItem>(); 64 65 public static void QueueOnMainThread(Action<object> taction, object tparam) 66 { 67 QueueOnMainThread(taction, tparam, 0f); 68 } 69 public static void QueueOnMainThread(Action<object> taction, object tparam, float time) 70 { 71 if (time != 0) 72 { 73 lock (Current._delayed) 74 { 75 Current._delayed.Add(new DelayedQueueItem { time = Time.time + time, action = taction, param = tparam }); 76 } 77 } 78 else 79 { 80 lock (Current._actions) 81 { 82 Current._actions.Add(new NoDelayedQueueItem { action = taction, param = tparam }); 83 } 84 } 85 } 86 87 public static Thread RunAsync(Action a) 88 { 89 Initialize(); 90 while (numThreads >= maxThreads) 91 { 92 Thread.Sleep(100); 93 } 94 Interlocked.Increment(ref numThreads); 95 ThreadPool.QueueUserWorkItem(RunAction, a); 96 return null; 97 } 98 99 private static void RunAction(object action)100 {101 try102 {103 ((Action)action)();104 }105 catch106 {107 }108 finally109 {110 Interlocked.Decrement(ref numThreads);111 }112 113 }114 115 116 void OnDisable()117 {118 if (_current == this)119 {120 121 _current = null;122 }123 }124 125 126 127 // Use this for initialization128 void Start()129 {130 131 }132 133 List<NoDelayedQueueItem> _currentActions = new List<NoDelayedQueueItem>();134 135 // Update is called once per frame136 void Update()137 {138 if (_actions.Count > 0)139 {140 lock (_actions)141 {142 _currentActions.Clear();143 _currentActions.AddRange(_actions);144 _actions.Clear();145 }146 for (int i = 0; i < _currentActions.Count; i++)147 {148 _currentActions[i].action(_currentActions[i].param);149 }150 }151 152 if (_delayed.Count > 0)153 {154 lock (_delayed)155 {156 _currentDelayed.Clear();157 _currentDelayed.AddRange(_delayed.Where(d => d.time <= Time.time));158 for (int i = 0; i < _currentDelayed.Count; i++)159 {160 _delayed.Remove(_currentDelayed[i]);161 }162 }163 164 for (int i = 0; i < _currentDelayed.Count; i++)165 {166 _currentDelayed[i].action(_currentDelayed[i].param);167 }168 }169 }170 }
Usage
Function {// run Loom asynchronously under multiple threads. runAsync () => {// This function will perform a large number of file read/write operations LoadLocalFile (); // return to the unity thread to continue running Loom. queueOnMainThread () =>{// this function is the unity function UnityFunction ();}}}
The general idea of this Loom class is to put the entire code block into multiple threads, and encapsulate the code to be run in the main thread in the list to be saved by delegation. The Updata function is a unity function, it is automatically executed once per frame. Therefore, he can determine whether the list has a task and execute the task to return to the main thread.