preface
- Multithreading is not commonly used in Unity, so the knowledge about it is not particularly thorough
- So this article will briefly talk about the role, limitations and usage of multithreading in Unity
Use of multithreading in Unity
In Unity, in addition to the main thread responsible for UI drawing, there are also co processes and multi threads.
The coroutine is accompanied by the "start" program of the main thread, which allows the program to run some methods within a specific time. The coroutine can call some UI and other attributes in Unity.
However, multithreading cannot directly process the game objects in Unity, because in Unity, you can only get the components, methods and game objects of the object in the main thread!
Use multithreading to:
- To load and configure download resources with threads, you need to display a progress bar
- Data processing in algorithm
What can be tuned using multithreading:
- C # basic variables
- In addition to the content in the API of UnityEngine
- Some basic structures defined by UnityEngined can also be called. For example, vector3 (structure) can be called, but Texture2d(class, root directory is Object) cannot.
Method 1: create multithreading in a normal way
Using Thread to open up a child Thread in Unity
Then, some business processes such as data calculation, value transfer and interaction with Android are carried out in this sub thread.
However, some API s in Unity cannot be called
Examples are as follows:
using System.Collections.Generic; using System.Threading; using UnityEngine; using UnityEngine.UI; public class ThreadTest : MonoBehaviour { void Start() { //Open up a child thread Thread childThread1 = new Thread(CallToChildThread); childThread1.Start(); } //What the child thread is responsible for public void CallToChildThread() { //Call the contents of the main thread Debug.Log(test()); //Print result: 666 } int test() { return 666; } }
Method 2: use the Loom plug-in to make multi-threaded calls
When Unity uses multithreaded development, one is to use the Loom plug-in for multithreading
Room is a tool class that is specifically responsible for the interaction between the main thread and the sub thread in Unity. The room plug-in has only one script, which can be imported and used in Unity
Which uses Loom to open up a sub thread method
Loom.RunAsync(() => { Thread childThread = new Thread(CallToChildThread); childThread.Start(); });
Call the data method in Unity using Loom multithreading:
//Use room to call the contents of the main thread Loom.QueueOnMainThread((param) => { ThreadTxt.text = "The child thread is turned on"; }, null);
The complete code example of calling the main thread with a child thread is as follows:
using System.Threading; using UnityEngine; using UnityEngine.UI; public class ThreadTest : MonoBehaviour { public Text ThreadTxt; void Start() { //Using Loom to open up a child thread Loom.RunAsync(() => { Thread childThread = new Thread(CallToChildThread); childThread.Start(); }); } public void CallToChildThread() { //Use room to call the contents of the main thread Loom.QueueOnMainThread((param) => { ThreadTxt.text = "The child thread is turned on"; }, null); } }
The tool class code of the room plug-in is as follows:
using UnityEngine; using System.Collections; using System.Collections.Generic; using System; using System.Threading; using System.Linq; public class Loom : MonoBehaviour { public static int maxThreads = 8; static int numThreads; private static Loom _current; //private int _count; public static Loom Current { get { Initialize(); return _current; } } void Awake() { _current = this; initialized = true; } static bool initialized; public static void Initialize() { if (!initialized) { if (!Application.isPlaying) return; initialized = true; var g = new GameObject("Loom"); _current = g.AddComponent<Loom>(); #if !ARTIST_BUILD UnityEngine.Object.DontDestroyOnLoad(g); #endif } } public struct NoDelayedQueueItem { public Action<object> action; public object param; } private List<NoDelayedQueueItem> _actions = new List<NoDelayedQueueItem>(); public struct DelayedQueueItem { public float time; public Action<object> action; public object param; } private List<DelayedQueueItem> _delayed = new List<DelayedQueueItem>(); List<DelayedQueueItem> _currentDelayed = new List<DelayedQueueItem>(); public static void QueueOnMainThread(Action<object> taction, object tparam) { QueueOnMainThread(taction, tparam, 0f); } public static void QueueOnMainThread(Action<object> taction, object tparam, float time) { if (time != 0) { lock (Current._delayed) { Current._delayed.Add(new DelayedQueueItem { time = Time.time + time, action = taction, param = tparam }); } } else { lock (Current._actions) { Current._actions.Add(new NoDelayedQueueItem { action = taction, param = tparam }); } } } public static Thread RunAsync(Action a) { Initialize(); while (numThreads >= maxThreads) { Thread.Sleep(100); } 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; } } // Use this for initialization void Start() { } List<NoDelayedQueueItem> _currentActions = new List<NoDelayedQueueItem>(); // Update is called once per frame void Update() { if (_actions.Count > 0) { lock (_actions) { _currentActions.Clear(); _currentActions.AddRange(_actions); _actions.Clear(); } for (int i = 0; i < _currentActions.Count; i++) { _currentActions[i].action(_currentActions[i].param); } } if (_delayed.Count > 0) { lock (_delayed) { _currentDelayed.Clear(); _currentDelayed.AddRange(_delayed.Where(d => d.time <= Time.time)); for (int i = 0; i < _currentDelayed.Count; i++) { _delayed.Remove(_currentDelayed[i]); } } for (int i = 0; i < _currentDelayed.Count; i++) { _currentDelayed[i].action(_currentDelayed[i].param); } } } }
summary
-
There are many inconveniences in using multithreading in Unity. Generally speaking, with the existence of coprocessing, multithreading will not be used again
-
Including using the Loom plug-in is not particularly convenient
-
Therefore, different people have different opinions. If you encounter some non particularly complex operations, you can use the collaborative process!
-
Xie Cheng's learning articles are here. Interested partners can come and have a look!