Unity Multithreading (thread) and main thread (Mainthread) interact using the class--loom tool to share
by D.s.qiu
Respect the labor of others, support the original, reproduced please specify the source: http.dsqiu.iteye.com
developer, who is familiar with unity, knows that threads in unity cannot use Unity's objects, but can use Unity's value-type variables, such as Vector3. This makes the thread in unity is very chicken and lame, because many functions are unityengine class or function call, for which can be used in multi-threaded, wind and rain is summarized as follows:
0. variables (all pointing to the same memory address) are shared
1. API that is not unityengine can be run on a sub-thread
2. The basic structure defined by Unityengine (int,float,struct defined data type) can be computed in sub-threading, such as Vector3 (Struct), but not texture2d (class, Root parent Class is object).
3. Unityengine defines the basic types of functions that can be run on a sub-thread, such as
int i = 99;
Print (i.ToString ());
Vector3 x = new Vector3 (0,0,9);
X.normalize ();
The function of a class cannot be run on a sub-thread
Obj.name
The actual is the Get_name function, the sub-thread is reported error: Get_name can only is called from the main thread.
Texture2d tt = new texture2d (10,10);
The actual call Unityengine in the Internal_create, sub-thread report error: Internal_create can only be called from the main thread.
Other transform.position,texture.apply () and so on are not allowed to run in sub-threads.
Conclusion: Sub-threading can do basic types of calculations, as well as non-unity (including. NET and SDK) APIs.
D.s.qiu felt that unity had made this limitation, primarily that unity's function execution mechanism was a frame sequence call, and even the execution mechanism of Unity's coroutine was determined, If you can use multithreading to access Unityengine objects and APIs, you have to consider synchronization issues, that is, unity does not have a multi-threaded mechanism, the process is only to achieve a delay or when the specified conditions are satisfied to continue to execute the mechanism.
Our project currently has no more time-consuming calculations, so we have not seen the use of thread. Had never been too concerned about the aspect of things, until the unitygems.com see loom this class, breathtaking AH. Direct the introduction of others (no need to translate):
Threads on a loom
Our class is called loom. Loom lets you easily run code on another thread and has this other thread run code on the main game thread when it needs To.
There is only and functions to worry about:
- RunAsync (Action) which runs a set of statements on another thread
- Queueonmainthread (Action, [optional] float time)-which runs a set of statements on the main thread (with an optional Del ay).
You access loom using loom.current-it deals with creating a invisible game object to interact with the games main Threa D.
We only need a relationship two functions: RunAsync (Action) and Queueonmainthread (action, [optional] float time) can easily implement a function of two pieces of code in the C # thread and unity's main thread to cross-run. The principle is also simple: Use the thread pool to run Runasync function, run Queueonmainthread (acition, [optional] float time) incoming function in update.
Directly post the source code, for reading:
Using Unityengine;Using System.Collections;Using System.Collections.Generic;Using System;Using System.Threading;Using System.Linq;PublicClass loom:monobehaviour{ PublicStaticint maxthreads =8; Staticint numthreads; Privatestatic loom _current; Privateint _count; PublicStatic Loom Current{ Get { Initialize (); return _current; }} void Awake (){ _current =This initialized =True} StaticBOOL initialized; Staticvoid Initialize (){ if (!initialized) { if (! application.isplaying) Return initialized =True var g =New Gameobject ("Loom"); _current = g.addcomponent<loom> (); } } Private list<action> _actions =New List<action> (); Publicstruct Delayedqueueitem{ Publicfloat time; Public action action;} Private list<delayedqueueitem> _delayed =New List<delayedqueueitem> ();List<delayedqueueitem> _currentdelayed =New List<delayedqueueitem> (); PublicStaticvoid Queueonmainthread (Action action){ Queueonmainthread (Action,0f);} PublicStaticvoid Queueonmainthread (Action action,Float time){ if (Time! =0) { Lock (current._delayed) { Current._delayed. ADD (New Delayedqueueitem {time = Time.time + time, action = action}); } } Else { Lock (Current._actions) { Current._actions. ADD (action); } }} PublicStatic Thread RunAsync (Action a){ Initialize (); while (Numthreads >= maxthreads) { Thread.Sleep (1); } Interlocked.Increment (Ref numthreads); ThreadPool.QueueUserWorkItem (Runaction, a); ReturnNull} PrivateStaticvoid 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<action> _currentactions =New List<action> (); Update is called once per frame void Update (){ Lock (_actions) { _currentactions.clear (); _currentactions.addrange (_actions); _actions. Clear (); } foreachvar aIn _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 (); } }}
How to implement a function in the use of multi-threaded computation and keep the function in the order of code execution, the impression that the use of multithreading is to get rid of the code block order execution, but here is the original function is split into two parts: part of the C # thread, the other is used in unity Mainthread , how to solve it, but also to see examples:
Scale a mesh on a second threadvoid Scalemesh (Mesh mesh,Float scale) { Get the vertices of a mesh var vertices = mesh.vertices; Run the action on a new threadLoom.runasync (() =>{ Loop through the vertices Forvar i =0; I < vertices. Length; i++) { Scale the vertex Vertices[i] = vertices[i] * scale; } //run Some code on the main thread //to update the Mesh Loom.queueonmainthread (() =>{ Span class= "indent" > //set the Vertices mesh.vertices = vertices; //recalculate the bounds< Span class= "indent" > mesh. Recalculatebounds (); });
This example is a good example of using a closure (closure) and lambda expression to indent the vertices of a mesh. After reading the example, is not very many time-consuming functions in the project to split out, D.s.qiu would like to use this method to improve the underlying mechanism of Ngui (see performance can not be improved).
Summary:
D.s.qiu in the programming technology master or a rookie, thread or stay in the implementation of Runable interface or inherit the thread of a level, the understanding of multithreaded programming is only bucket. Originally I thought that the implementation of loom would be more complicated, when I found that only 100 lines of code is greatly amazed, this also benefited from the current language improvements, at least from the language use of the convenience of a great progress.
With loom this tool class, there is a workaround for many time-consuming calculations involving Unityengine objects:
such as in the scene with a * algorithm for a large number of data calculation
Manipulating a large number of vertices in a warp mesh
Continue to run upload data to the server
Two-dimensional code recognition and other image processing
Loom simple and ingenious, admire the author of Loom.
If you have any suggestions or comments on D.s.qiu can comment on the post, or e-mail ([email protected]) Exchange, your encouragement and support is my driving force, I hope to have more and better share.
Unity Multithreading (thread) and main thread (Mainthread) interact using the class--loom tool to share