Unity multi thread (Thread) and the main thread (MainThread) interaction using c

Unity multi thread (Thread) and the main thread (MainThread) interaction using class -- Loom tools to share

By D.S.Qiu

Respect other people's work, to support the original, reproduced please indicate the source: http.dsqiu.iteye.com

 

         Familiar with Unity developer all know object thread cannot use in Unity Unity, but you can use the Unity value type variables, such as Vector3 etc. This makes the thread in the Unity show very chicken ribs and bad, because a lot of function is UnityEngine class or function call, for which can be used in the multi thread, the rain washed were summarized as follows:

 

0 variables (could point to the same memory address) are shared

1 is not a UnityEngine API in a thread running

The basic structure of 2 of the definition of UnityEngine (int, float, Struct defined data types) can be calculated in the thread, such as Vector3 (Struct), but Texture2d (class, root parent is Object) can't.

3 UnityEngine defines the basic types of function can be in thread running, such as

       int i = 99;

       print (i.ToString());

       Vector3 x = new Vector3(0,0,9);

       x.Normalize();

The function cannot be in thread running

       obj.name 

The actual get_name function, branching process error: get_name can only be called from the main thread

       Texture2D tt = new Texture2D(10,10);

The actual will call UnityEngine, Internal_Create, branching process error: Internal_Create can only be called from the main thread

Other transform.position, Texture.Apply () and so on are not running in the branching process.

Conclusion: thread can do the calculation of basic types, and non Unity (including.Net and SDK) of API.

Making making D.S.Qiu think Unity did this limitation, Unity is mainly a function execution mechanism is called frame sequence, Even Unity coroutine Coroutine enforcement mechanism are determined, If the object can be used to access the UnityEngine multi thread and API will have to consider the synchronization problem, That is to say the mechanism of Unity in fact no multithreading, The coroutine is reaching a delay or when the specified conditions are satisfied is a mechanism to continue.

Making making our project at present there is no calculation is time-consuming, so also do not see the use of Thread. I have been not considered things, until you see the Loom class in the UnityGems.com, as the acme of perfection. Direct posted their introduction (don't need translation laugh laugh):

Threads on a Loom

Our class is called Loom.  Loom lets you easily run code on another thread and have that other thread run code on the main game thread when it needs to.

There are only two functions to worry about:

You access Loom using Loom.Current - it deals with creating an invisible game object to interact with the games main thread.

        

Making making we need only two functions: RunAsync (Action) and QueueOnMainThread (Action, [optional] float time) can easily achieve a function of the two cross code runs in the main thread and C# thread in Unity. The principle is simple: use the thread pool to run RunAsync (Action) function, run QueueOnMainThread in Update (Acition, [optional] float time) afferent function.

 

Posting the source code, to read:

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;
	
	static void 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>();
	public struct DelayedQueueItem
	{
		public float time;
		public Action action;
	}
	private List<DelayedQueueItem> _delayed = new  List<DelayedQueueItem>();

	List<DelayedQueueItem> _currentDelayed = new List<DelayedQueueItem>();
	
	public static void QueueOnMainThread(Action action)
	{
		QueueOnMainThread( action, 0f);
	}
	public static void 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);
			}
		}
	}
	
	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;
		}
	}
	
	

	// 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();
		}
		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();
		}
		
		
		
	}
}

 

 

Making making how implementation using multithreading and keep the code function in a function within the order, is to get rid of execution of a code block in order to use multiple threads in the impression, but here is a function of the original split into two parts: a part of the C# thread used in another department, or in Unity MainThread, how to solve it, must look at the example:

 

//Scale a mesh on a second thread
void ScaleMesh(Mesh mesh, float scale)
{
    //Get the vertices of a mesh
    var vertices = mesh.vertices;
    //Run the action on a new thread
    Loom.RunAsync(()=>{
        //Loop through the vertices
        for(var 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(()=>{
            //Set the vertices
            mesh.vertices = vertices;
            //Recalculate the bounds
            mesh.RecalculateBounds();
        });
 
    });
}

Making making this example is the apex of Mesh scaling, is also a closure (closure) a good example and lambda expression. Through the examples, Is it right? Are project some time-consuming function to split out, D.S.Qiu wanted to use this method to improve the underlying mechanism under NGUI (see performance cannot be improved).

 

 

 

Summary:

Making making D.S.Qiu programming technology to master is still a rookie, Thread still remains at the same level to implement the Runable interface or inherited Thread, understanding of multithreaded programming is just a drop in the bucket. I originally thought that the implementation of Loom will be more complex, when I discovered that only 100 lines of code is amazing, which also benefited from the now language improvement, at least from the convenience of language use, or have great progress.

Making making with the Loom tool, in many UnityEngine objects time-consuming calculation can still get a solution:

Making making making making as in the scene with the A* algorithm for large amount of data

Making making making making operation of large number of vertices in the mesh deformation
Making making making making continued to run to upload the data to the server
Making making making making two-dimensional code recognition image processing

Making making Loom simple and ingenious, admire the author of Loom.

 

Making making if you have any suggestions or comments can comment at the end of the D.S.Qiu, or email) (AC, your encouragement and support is my motivation, hope to have more and better share.

Making making reprint please indicate the source in the:

More exciting, please pay attention to D.S.QiuBlogAnd micro-blog (ID: static wind)

 

Reference resources:

①UnityGems:

②Xiaoke's Blog:

Feng Yu Chong

Posted by Eric at October 31, 2014 - 9:16 AM