Go to Top

Learn when it's the right time to use threads for your game and get to grips with some of the complexities they impose. See how easy it can be to add a multithreaded functions to your game...

Motivation

You should read this article if you are interested in making use of multiple threads for your game. Threading is a fairly complicated topic, but if you master it then there are real benefits for performance when using hardware that has multiple processors or when it is hard to divide processing into manageable chunks.

Threads are great for:

  • Algorithms like A* that need to process a lot of data describing the map of your level
  • Manipulating huge numbers of points, like deforming a mesh
  • Long running uploads to a server
  • Image processing like QR code recognition
Use a thread if you have a lot of processing and little interaction with Unity objects until it is complete, use a coroutine otherwise.

Threads

A thread is a process that runs at the same time as other threads in your program.  On machines with multiple processors then this execution is may be truly simultaneous, depending on whether there are more threads than there are processing cores available.

When programming Unity you always have the main game thread that executes all of the code in your scripts, you also have the option to create extra threads that will run at the same time as the main game.

In Unity you can only access Unity Components, object and Unity system calls from the main thread.  Any attempt to access such items from a second thread will fail and raise errors.  This is a pretty significant limitation and this article will show you ways to work with and around it.

The Myth of Continuity

So when you write code you believe that when a function starts it continues up to the point when it returns unless you do something to move execution to another function - but that isn't what happens.  At any time your code may be just put to sleep by the processor and another piece of code starts running, when the OS decides its time for your code to get some more time, it wakes up and carries on as if nothing had happened.

Your thread can be suspended on any statement in machine code, one high-level language statement will be turned into many machine code statements, so your program could be suspended in the middle of an instruction you wrote.

Now all that is well and good and you don't care.  That is you don't care until you start thinking about threads.  When you have multiple threads they could be simultaneously accessing the same variable or class at the same time, or you could have your code suspended and the value of a variable be changed before the rest of the statement executes.

In this example the first thread is interrupted after loading the value of A into a CPU register ready for the addition of a 1.  The second thread also reads the value of A, still 50, takes 1000 away from it an stores the value in A, at this point A = -950.  Now thread 1 resumes, adds 1 to the 50 it has in the register and stores the result in A.  A now = 51, the -950 has been completely lost.

Fundamentally this makes threads very hard to work with and to make sure that situations like this do not happen you have to take a lot of precautions when accessing variables or memory that might be used by more than one thread at a time.

Unity decided just to avoid the problem with all of their system and framework objects by deeming their access from another thread to be invalid.

Lock Up Your Daughters

So the answer to having problems with variables being concurrently modified is to ensure that only one thread has access to the variable at one time - clearly you want to limit the amount of time that this occurs for as it has effectively meant that you are not allowing multiple threads to work at the same time, sort of defeating the point.

C# has the keyword lock which ensures only one thread can be inside a particular object at a particular time.  I say object because you cannot lock a value type or a primitive.

int a = 50;

object guard = new object();

void ThreadOneCode()
{
     //Some code here

     lock(guard)
     {
         a = a + 1;
     }

     //More code here

}

void ThreadTwoCode()
{
     //Some code here

     lock(guard)
     {
         a = a - 1000;
     }

     //More code here
}

Everything inside the lock(guard) {...} guarantees that only one thread using guard can access it at a time.  You can use any suitable object.

Now you can get into all sorts of problems when you need to lock more than one thing nested inside each other.  You can end up in a circumstance where to get your inner lock, something else needs to happen that cannot, because it relies on getting the same thing as your outer lock (which it can't have because you already have it locked).  This is called deadly embrace - an impossible to break cycle that just freezes everything up.  If you program seriously with threads, this is going to happen to you at some point.

If you are new to threading, try very hard not to write things that share memory or variables if at all possible.  Pass variables to threads, pass them back, but try not to use the same memory.
There are many other ways that threads can be synchronised, but lock is the only one built into the language, all of the others require the construction of system objects to maintain them.  If you  go down that route there are great ways of making efficient code - like locks that allow many things to read a value but only a single thread to own the object when its written to.

Practical Threading in Unity

So in Unity you can only process your own class instances and Unity value types (like Vector3, Quaternion etc) only - as mentioned this makes things a bit limited.  You could though do something like modify the vertices for a mesh on a second thread and then pass the array of Vector3s back to the main thread to actually update the object.

You could write some pathfinding code that uses A* to find a route from some point to another one on your map.

Whatever you do you are going to have to pass things to and from your new thread and the main game thread if you want it to have any real effect!

So how can we write neat code that works across threads without cluttering our classes up with lots of buffers and flags to indicate when things are ready to be processed with all of the incumbent ifs and checks?  It's that clutter that usually leads to bugs and stops people from really using threads efficiently or sometimes at all.

Well using closures and anonymous functions you can build a framework that makes these things easy.  I'm not going to list the whole of that code in this tutorial, but it's available here, but I am going to show you how to use it.

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:

  • 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 delay).

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

Here's an example of using Loom to update a mesh by multiplying out all of the vertices

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

		});
	}

This is a great example of using closures.  The Action (a method taking no parameters and returning nothing) that is run on the second thread is created using a lambda function (or an anonymous function).  The magic of closures is that these have access to all of the variables in your class and in the parameters and local variables of your function.

You define a lambda function using ()=>{ ... } and everything inside that function is run on a new thread.

When the vertices have been updated we need to modify the mesh on the main thread, so we use QueueOnMainThread which will run during the next time Update cycles are processed (this frame or the next frame depending on when it is called).  QueueOnMainThread also takes an Action so we use exactly the same technique to pass the updated vertices back to the original mesh. Cool!

Source Code

Here is the code for Loom:

 

using UnityEngine;
using System.Collections.Generic;
using System;
using System.Threading;
using System.Linq;


public class Loom : MonoBehaviour
{
    void OnApplicationQuit()
    {
        _quitting = true;
    }
    static bool _quitting;
    private static Loom _current;
    private int _count;

    public static Loom Current
    {
        get
        {
            Initialize();
            return _current;
        }
    }

    static bool _initialized;
    static int _threadId;

    public static void Initialize()
    {
        if (!Application.isPlaying || _quitting)
            return;
        var go = !_initialized;
        if (!go && _threadId == Thread.CurrentThread.ManagedThreadId && _current == null)
            go = true;

        if (go)
        {
            foreach (var loom in Resources.FindObjectsOfTypeAll(typeof(Loom)).Cast<Loom>())
                DestroyImmediate(loom.gameObject);
            var g = new GameObject("Loom");
            _current = g.AddComponent<Loom>();
            _initialized = true;
            _threadId = Thread.CurrentThread.ManagedThreadId;
        }

    }

    void OnDestroy()
    {
        _actions.Clear();
        _delayed.Clear();
        if (_current == this)
        {
            _initialized = false;
        }
    }

    private readonly List<Action> _actions = new List<Action>();
    public class DelayedQueueItem
    {
        public float time;
        public Action action;
        public string name;
    }
    private readonly List<DelayedQueueItem> _delayed = new List<DelayedQueueItem>();

    public static void QueueOnMainThread(Action action, string name)
    {
        QueueOnMainThread(action, 0, name);
    }

    public static void QueueOnMainThread(Action action, float time, string name)
    {
        if (!Application.isPlaying)
            return;
        if (Math.Abs(time - 0) > float.Epsilon || !string.IsNullOrEmpty(name))
        {
            lock (Current._delayed)
            {
                DelayedQueueItem existing = null;
                if (!string.IsNullOrEmpty(name))
                    existing = Current._delayed.FirstOrDefault(d => d.name == name);
                if (existing != null)
                {
                    existing.time = Time.time + time;
                    return;
                }
                var queueItem = new DelayedQueueItem();
                queueItem.name = name;
                queueItem.time = Time.time + time;
                queueItem.action = action;
                Current._delayed.Add(queueItem);
            }
        }
        else
        {
            lock (Current._actions)
            {
                Current._actions.Add(action);
            }
        }

    }

    /// <summary>
    /// Queues an action on the main thread
    /// </summary>
    /// <param name='action'>
    /// The action to execute
    /// </param>
    public static void QueueOnMainThread(Action action)
    {
        QueueOnMainThread(action, 0f);
    }
    /// <summary>
    /// Queues an action on the main thread after a delay
    /// </summary>
    /// <param name='action'>
    /// The action to run
    /// </param>
    /// <param name='time'>
    /// The amount of time to delay
    /// </param>
    public static void QueueOnMainThread(Action action, float time)
    {
        QueueOnMainThread(action, time, null);
    }

    /// <summary>
    /// Runs an action on another thread
    /// </summary>
    /// <param name='action'>
    /// The action to execute on another thread
    /// </param>
    public static void RunAsync(Action action)
    {
        var t = new Thread(RunAction)
        {
            Priority = System.Threading.ThreadPriority.Normal
        };
        t.Start(action);
    }

    private static void RunAction(object action)
    {
        ((Action)action)();
    }

    readonly Action[] _toRun = new Action[4000];

    // Update is called once per frame
    void Update()
    {
        if (Current != this)
        {
            if (Application.isPlaying)
                DestroyImmediate(gameObject);
            return;
        }
        if (!Application.isPlaying)
        {
            _actions.Clear();
            _delayed.Clear();
            return;
        }
        var count = Mathf.Min(_actions.Count, 4000);
        lock (_actions)
        {
            _actions.CopyTo(0, _toRun, 0, count);
            if (count == _actions.Count)
                _actions.Clear();
            else
                _actions.RemoveRange(0, count);
        }
        for (var i = 0; i < count; i++)
        {
            try
            {
                _toRun[i]();
            }
            catch (Exception e)
            {
                Debug.LogException(e);
            }
        }

        lock (_delayed)
        {
            count = 0;
            for (var i = _delayed.Count - 1; i >= 0 && count < 3999; i--)
            {
                if (!(_delayed[i].time <= Time.time))
                {
                    continue;
                }
                _toRun[count++] = _delayed[i].action;
                _delayed.RemoveAt(i);
            }
        }

        for (var i = 0; i < count; i++)
        {
            try
            {
                _toRun[i]();
            }
            catch (Exception e)
            {
                Debug.LogException(e);
            }
        }


    }



    void OnLevelWasLoaded()
    {
        _actions.Clear();
        _delayed.Clear();
    }
}

 

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

		});
	}
, , , , , , ,

67 Responses to "Threads"

  • Valentin
    November 6, 2012 - 10:40 am Reply

    Good article.
    Have you actually tested what performance increase this method gives?
    I guess all these closures add some boxing/unboxing time.

  • whydoidoit
    November 6, 2012 - 1:11 pm Reply

    Actually closures don’t need to do boxing/unboxing as they turn the variables and parameters of your functions into a compiler generated class which is then automagically merged with your normal class when using the none close variables. That does of course mean you are creating many instances of these classes which will eventually need garbage collection – though I believe the compiler is optimised for this as it never seems to have the size of impact I would be expecting.

  • Xiaoke
    February 11, 2013 - 9:01 am Reply

    Good job~~thanks for share!

    • whydoidoit
      March 27, 2013 - 8:59 am Reply

      Nice! Very interesting results!

  • coAdjoint Tom
    March 30, 2013 - 10:56 am Reply

    This is excellent information, as per usual. If anyone is interested in a video tutorial on threading, I’ve made one here. As well as basic information I also show you how to make a threaded task queue in Unity.

  • Domarius
    April 2, 2013 - 3:06 am Reply

    Amazing! When I got to the bottom of the article, I had to scroll back and re-read the last bit a few times to make sure I wasn’t mistaken; I couldn’t believe you’d done all the work for us and it was that easy – just paste in your code around a section that needs speeding up and boom – threading.

    But it really is! Talk about having multi-threading handed to you on a silver platter. Once you make sure you choose a segment of code that can do some heavy work by itself, and set up the main program to be able to wait an arbitrary amount of frames till that process is done, you’re good! As long as it doesn’t interface with any Unity reference types.

    But Debug.Log works just fine! Which is useful… because if a run-time error happens in the threaded code, no error is thrown – the process just silently stops, and you need to use Log outputs to narrow down where the halt is… helps to make sure that process is working before bundling it up in a thread. But it’s also trivial to remove the thread code around the edges and let it run in the main thread, albeit with a huge lock up while you wait for the process.

    • whydoidoit
      April 2, 2013 - 7:45 am Reply

      Yeah – thankfully you can Log – it was a real relief when I found that out myself :)

      • mrzoom
        April 28, 2013 - 7:40 pm Reply

        Thanks so much! yes print works although yield causes bugs in QueueOnMainThread.

        I have it running on an infinite landscape, it’s really great!!! although i am having trouble for some marching cubes – i put threading codes in the maths points compute function and then no mesh appears, and it causes indexoutofrangeerror with the generic list also:

        function ComputePoints()
        {
        Loom.RunAsync(function() {
        var division: float = 1.0/(size -1);

        for (var z:int = 0; z < size; z++) // z – blue
        for (var y:int = 0; y < size; y++) // y – green
        for (var x:int = 0; x < size; x++) // x – red
        {
        var vx:float = x *division;
        var vy:float = y *division;
        var vz:float = z *division;

        //print("points" + x);
        var value:float;
        value=equation1(vx,vy,vz);
        Loom.QueueOnMainThread(function() {
        values.Add(value);
        points.Add(Vector3(vx,vy,vz));
        });

        }

        //
        });//
        }

  • Water Particles « UnityCoder – Unity3D
    April 13, 2013 - 12:52 am Reply

    [...] TODO: – 3D version? – Add Blobmesh = water? – Optimize..if can.. – Different fluidish materials? (mass, friction, break-ability?) – Sand simulation? (ground digging with excavator..or maybe better using the eulerian water sim grid?) – Test threading? http://unitygems.com/threads/ [...]

  • mrzoom
    April 28, 2013 - 9:19 pm Reply

    Can Loom.RunAsync be run on its own excluding QueueOnMain? what order executions can cause bugs using the loom routines?

  • FireStarter
    May 11, 2013 - 11:38 am Reply

    How do I actually put the file available for download in the project? What is the file type?

  • whydoidoit
    May 14, 2013 - 7:03 am Reply

    It’s a unitypackage so either double click it or use Assets/Import Package/Custom Package

  • XiaoHong
    June 2, 2013 - 10:53 am Reply

    Hi, I can’t seem to be able to find the author of this page but I assume it’s whydoidoit?

    First of all, very nice article, the best on the topic of “unity + threading” I’ve found so far. This should have been the 1st item to show up on Google, sadly it was not.

    Some questions and observations:

    1. For the method QueueOnMainThread(Action action, float time)
    the delay time functionality does not seem to work.
    Using a non zero value(0.1f) for “time” gives the error:

    get_time can only be called from the main thread.
    Constructors and field initializers will be executed from the loading thread when loading a scene.
    Don’t use this function in the constructor or field initializers, instead move initialization code to the Awake or Start function.

    2. With maxThreads = 8 when I tried to run more than 8 tasks/actions in Loom.RunAsync the whole game would lag, my first guess was that instead of the 9th task being queued properly, it would hang the game until an empty thread slot was freed.
    For example, I have 9 identical tasks, the single threaded operation for one task is 0.5s.
    Using Loom.RunAsync, if I add 8 tasks, time used is 0.01s (time elapsed on main thread before and after adding the tasks), all 8 run for 0.5s and return results to main thread. Nothing weird so far. Now I add the 9th task directly under the 8 tasks, the main thread hangs for 0.5s. I don’t think that this should happen.

    After reading through Loom.cs, and doing some more testing, my understanding now is that
    public static int maxThreads
    is not the maximum threads but the maximum of queued Tasks, and should be set accordingly. I noticed that you are sending tasks to the ThreadPool and this manages the maximum number of threads.
    see: http://www.c-sharpcorner.com/UploadFile/1d42da/threading-pooling-in-C-Sharp/

    The actual maximum threads in the pool should be set by ThreadPool.SetMaxThreads(int workerThreads, int completionPortThreads);

    So to set the maximum number of queued tasks set maxThreads (I set this to 100000)
    and to set the maximum number of threads set ThreadPool.SetMaxThreads(int, int); in the Initialize() method

    I set ThreadPool.SetMaxThreads(2, 0) to and now it seems to be working as I expected.

    3. Can I use the code you provided: \whydoidoit.com\Radical\System\Loom.cs in my games for free? Are there any licence at all for this piece of code? Did you write it? I’m asking because there is the Loom assest store item that’s not free:
    http://u3d.as/content/michiel-frankfort/loom-multi-threading-framework/4fx
    I don’t want to run into legal issues after publishing a game.

    4. Now that I seem to have threading working properly, I use worker threads to generate meshes and assign them to gameObjects. The problem I now face is that the worker threads are generating the meshes so fast that the main thread is having trouble to keep up with rendering them, and this causes the main thread to be unresponsive. I guess one way to settle this is to add in manual delays to the worker threads, but that feels ugly. Anyone have better suggestions?

  • Michał Wróblewski
    July 2, 2013 - 10:56 am Reply

    Hi,

    I’ve found a bug in Loom. When it’s removed from scene and reinitialized, initialized flag is still true so no new instance is created. Setting initialized to false in OnDisable fixes the problem.

    Michał

  • Clint Hobson
    July 29, 2013 - 6:31 am Reply

    VERY IMPORTANT GOTCHA
    If you’re launching new threads from within a loop, things will go screwy. Eg. a coroutine that waits for available thread count to go down within a loop, then launches a new thread to process a waiting object. Only the last object will be processed, and all the threads will work on it. This is due to Loom’s implementation of “Anonymous delegates”.

    “Access to modified closure” http://confluence.jetbrains.com/display/ReSharper/Access+to+modified+closure
    When you have a loop where you specify a variable to be used in an anonymous function or delegate or something special – it will allow that variable to change within the loop before the delegate gets it. In my case, Loom uses an anonymous function syntax to launch the thread, and the threads were having their “region” variable changed underneath them. Putting that in a new temporary variable didn’t work, I had to also put the action of launching a new thread in a separate function. and the function call was in the loop (also has to do with loop unrolling in the compiler, I understand)

  • Clint Hobson
    July 29, 2013 - 6:35 am Reply

    Quick comparison of “Loom” in the asset store (a different product)

    Don’t get these two confused – this one is free and available on this page. The one in the asset store is much more elaborate, and yet even easier to use.

    I believe it’s simply a case of “you get what you pay for” I highly recommend the asset store Loom, it will save you a lot of extra work, especially if you simply want to process a large number of objects on however many available threads there are. That’s one function call – you just pass it a function to use to process each object, and an array of objects to process. It will by default use any available threads however many cores there are, but you can optionally provide a number of threads to max out to.

    If you can’t afford the $30, then this free version of Loom here will certainly do the job – though you have to watch out for the gotcha I posted above due to its use of anonymous function syntax, and you will have to do extra programming to keep track of thread progress and how many max threads are running. Also you have no way of aborting running threads.

    • whydoidoit
      July 29, 2013 - 6:46 am Reply

      A very good point about closures and looping variables that I really should have included myself. Thanks!

    • whydoidoit
      July 29, 2013 - 7:12 am Reply

      I should add that personally I always use the anonymous delegate syntax as I like to keep relevant code in a single section. Closures are very powerful, so long as you work around the peculiar syntax when it comes to looping constructs with a foreach and the modification of the closure variable (which is one small downside of using closures in C# sadly).

      It would be trivial to add a return value to RunAsync that contains the thread to stop should you wish to not have the thread control its own destiny.

      This is an article explaining threads and how to work with them an closures, it certainly isn’t a commercial product. My own version of this Loom class serves me in a number of commercial projects.

      • Clint Hobson
        August 2, 2013 - 1:43 am Reply

        I’ve come back here to be honest – I reverted back to this free version of Loom. I just had unexplained problems with StartThreadedWorkloadExecution in the asset store version, a function which takes an array of objects, a function pointer to process them with, and makes sure they all get done while never exceeding max threads (a value you specify, or default to number of cores), and you monitor an “isBusy” variable in a coroutine to see when all the threads are done. It seems cool… but I had issues cancelling the process while salvaging processed objects. Things came out messed up.

        This free version of Loom, I guess it’s simpler, and that’s perhaps what’s saving me here – I’m keeping track of thread count myself (and using SystemInfo.processorCount to determine number of cores on the hardware)

        Look, I won’t go as far as saying the asset store version is buggy – that’s for someone else to verify 100%. It certainly has more cool features like being able to call a command from the thread that runs on the main thread (eg. if you want to create a Unity Mesh) and a “safe mode” boolean for each thread, which will log errors to the main thread!

        I’m working around not having the function to call something on the main thread, by using a coroutine on the main thread that monitors the objects for when they need a mesh created, and then does it. Works well enough, possibly a bit more complicated to read the code, but no effect on performance.

        So I wanted to sum up by saying this free version definitely does the trick, I appreciate your point about the Closures, and I’ll probably be sticking with your version of Loom to the end of the project, hahah.

        My only suggestion is, it would probably be really helpful to others to update the article with an example of when you’ll run into “modified closure” and how to work around it – I really feel like I was blessed by an angel to happen to run into the right person on Unity forum who happen to see my post, and happen to know exactly what was happening!

      • Clint Hobson
        August 2, 2013 - 1:49 am Reply

        Regarding the “return value for RunAsync” is that something you meant you could add, or were suggesting I could add myself? I couldn’t work it out just now, couldn’t find a distinct “thread” object to return – I can tell that’s where your code leaves off and C# threading comes in – but that’s beyond my understanding :)

  • cuocuo
    August 27, 2013 - 1:35 am Reply

    Waoo,This is very useful for me

  • cam chatpig
    October 3, 2013 - 3:56 pm Reply

    I think that everything published made a great deal of sense.
    But, what about this? what if you typed a catchier title?

    I am not saying your content isn’t solid, however what if you added a headline that grabbed
    folk’s attention? I mean Threads | Unity
    Gems is a little plain. You ought to look at Yahoo’s home page and note how they
    create article titles to get viewers interested. You might add a related video or a
    picture or two to get readers excited about everything’ve written.
    In my opinion, it could bring your website a little livelier.

  • Mike
    October 31, 2013 - 6:07 pm Reply

    I’ve just started fiddling with Loom – am I right in thinking that it requires the game to be unpaused in order to run any of its stuff? Getting Loom to make EditorApplication.isPaused = true works fine, but trying to get Loom to unpause it via the Main Thread doesn’t work.

    • whydoidoit
      January 12, 2014 - 9:18 am Reply

      Yeah – you can easily make a version that doesn’t require that though by making a version that doesn’t use Time.deltaTime – but uses Time.realTimeSinceStartup to work out when to run things which are paused.

  • Landon
    January 11, 2014 - 11:18 pm Reply

    What is the license on this asset? Can I use this on a commercial Unity Asset Store product? Under which terms?

    Overall I love this work, its great and allows you to easily multithread in Unity.

    Best Regards and eagerly awaiting a reply,

    Landon

    • whydoidoit
      January 12, 2014 - 9:16 am Reply

      All code on this website is MIT licensed, use it as you see fit! (Don’t confuse my Loom class with the Loom Asset on the Asset Store – they are different things – guess we both thought that looms dealt with threads!)

      • Landon
        January 13, 2014 - 12:38 am Reply

        Great man!

        Thanks a ton for your contribution to Unity’s community.

        Looks out for an asset called “CivGrid” coming to the asset store soon. Its a Civilization 5-like terrain generator(procedural). It’s on me if you ever decide your interested in it. (Or anything else from ‘Pixel Perfect Games’ once it hits the market)

        Thanks again!

  • DQvsRA
    January 22, 2014 - 10:04 am Reply

    I did a test today, and it’s work fine with listening output message from running process in Unity.
    private Process process = new Process();

    private void CheckBarcode()
    {
    process.StartInfo.FileName = “ciprocess.exe”;
    process.StartInfo.Arguments = “someparams”;
    process.StartInfo.UseShellExecute = false;
    process.StartInfo.RedirectStandardOutput = true;
    process.Start();
    Threaded.RunAsync(() =>
    {
    string line = process.StandardOutput.ReadLine();
    while (line != null)
    {
    UnityEngine.Debug.Log(“line:” + line);
    line = process.StandardOutput.ReadLine();
    Threaded.QueueOnMainThread(() =>
    {
    generator.DoWork(line);
    });
    }
    process.WaitForExit();
    });
    }
    Thank you!

  • Chuck
    January 27, 2014 - 7:58 am Reply

    Is there a way to execute two calls to RunAsync and wait for the first to complete before calling the second. In other words, is there a way to define a callback delegate so when the first completes it can fire an event to inform the next to run? I suppose I could just add this in but wanted to ask first in case I’m maybe looking at this wrong.

    • Chuck
      January 27, 2014 - 9:09 pm Reply

      Right now, I’m doing this…

      Invoke(“CreateCubeMesh”, 0);
      Invoke(“SpherefyCubeMesh”, .2f);

      …because the cube mesh create and spherefy are being called on there own background threads. However, since each method runs as async, spherefy gets called before the cube mesh is completely created. Not good. So the ‘Invoke’ method above allows time for the cube to finish, this works but obviously it’s not fool proof . Is there a better way I could use Loom as it is to ‘wait’ before running another async operation? Any suggestions?

  • antony
    January 27, 2014 - 1:32 pm Reply

    Hi, I wish to sell a procedural terrain addon with your fantastic code added into the program, and to provide this page and references so people would know that it is an amazing free addon included with my files. is that possible for me?

    • whydoidoit
      January 27, 2014 - 2:16 pm Reply

      Of course, you can use it however you like :)

  • Jon
    January 31, 2014 - 8:39 am Reply

    Making a game where there will be programmable lua computers. Lua instances will need to threaded. This just solved the problem of calling the C# methods from lua in a thread safe manner. You just made my week, thank you.

  • Igor
    March 31, 2014 - 5:46 pm Reply

    Unless I’m mistaken, I did not see any synchronization construct in your example code for the call to Loom.QueueOnMainThread. In other words, there is an unsafe critical section in that call because the update mesh.vertices = vertices; does not confirm that the thread updating vertices has terminated first.

    • whydoidoit
      March 31, 2014 - 6:43 pm Reply

      I think you are mistaken. The call to QueueOnMainThread happens after the vertices are complete and so will only happen in that circumstance, the next time the main thread checks for synchronisation calls.

      • Igor
        March 31, 2014 - 8:58 pm Reply

        I see. I somehow didn’t notice the call was internal.

  • Paul Cohen
    April 1, 2014 - 3:17 am Reply

    Hi,
    I’ve been using Loom Asset Store for threading, but would like to try this given some of the recent comments.

    However, I can open the source package in latest Unity.
    It’s about 3K and does not show up on Import Asset dialog either.

    Is there something wrong with the source download or a link to the source repository?

    ty!

    • whydoidoit
      April 1, 2014 - 4:47 am Reply

      I’ve modified it so that the latest source is in the post. Hopefully that is working without a bunch of my support libraries, let me know if you have a problem. One thing would be to use a recycled version of DelayedQueueItem (which my code does with other support stuff) as this reduces garbage to 0 if using Loom for delayed steps.

      • Paul Cohen
        April 1, 2014 - 5:15 am Reply

        Great! Ty!

  • Jon
    April 1, 2014 - 5:24 am Reply

    I’ve made a modifications to Loom that could be quite helpful to some. I added a new class “AsynRunner”. This class allows you to run tasks on a separate thread. In the Loom class, I added a “Dictionary” that contains the references to each AsyncRunner. I added a function to Loom.cs “AddAsyncThread(string)” to add a new element to the Dictionary, along with “QueueAsyncTask(string, Action)”, which allows me to run a lambda (“Action”) function on a specific thread.

    source:
    Loom.cs: http://hastebin.com/faroxitike.cs
    AsyncRunner.cs: http://hastebin.com/babiyineqe.cs

    • whydoidoit
      April 1, 2014 - 8:00 am Reply

      Great stuff, thx…

  • Paul Cohen
    April 1, 2014 - 6:06 am Reply

    Hi Jon,
    Thanks for the additions.

    Getting an error on the using Modding though, in both files.

    Seems related to ConsoleWpr, but not included.

    Is it needed?

    ty!

    • Jon
      April 1, 2014 - 6:44 am Reply

      Oh, yea, sorry about that. “ConsoleWpr” is a logging class in the “Modding” namespace of the project I’m using this in. They can be removed.

  • Corny
    April 9, 2014 - 8:54 pm Reply

    This is great stuff. But I’m having trouble if I want to resize my mesh. If I replace this line:

    var vertices = mesh.vertices;

    with this:

    var vertices = new Vector3[newSize];

    Then it does not work. Note this happens before the call to RunAsync. If I ‘q on main thread’ debug logs of progress, it shows it iterating, but if I print vertices.Length it’s always ZERO. Any idea what I’m doing wrong? Also, using Mono 4.1, it doesn’t seem to like my assemblies any more since I added Loom, cannot use debugger. Is this coincidental or can we not debug multithreaded code?

    • Corny
      April 9, 2014 - 10:43 pm Reply

      Actually, nevermind about my last question. My Unity/Mono was hosed, reinstalling fixed all that.

  • Beorn
    April 15, 2014 - 12:04 am Reply

    Wouldn’t your ScaleMesh function still be vulnerable to a “lost update problem” you describe above in your text, albeit at a higher level, since it doesn’t explicitly lock the mesh for update while updating the vertices? What happens if you update the mesh.vertices in another thread while the new vertices are being calculated?

    Or do you think implicitly relying on your knowledge of the code to ensure that doesn’t happen?

    • whydoidoit
      April 15, 2014 - 12:53 am Reply

      mesh.vertices always returns a copy of the vertices of the mesh, not a reference to the existing ones which is why it is vital to not keep getting them! So two things could independently change the vertices wholesale, but nothing could be changing the same vertices at the same time.

      • Beorn
        April 15, 2014 - 2:15 am Reply

        While they wouldn’t be stepping on each other’s toes since they iterate through different copies of the mesh vertices, one would still get whatever updates they did overwritten – it’s still a “lost update problem”, or?

        • whydoidoit
          April 15, 2014 - 4:52 am Reply

          Yes you would have to ensure that you weren’t doing it at the same time or you could lose updates. Normally you just have this on a second thread to keep the game running

  • PranavSathy
    April 18, 2014 - 7:49 pm Reply

    Calling QueueOnMainThread always results in a get_isPlaying can only be done on the main thread issue,
    however I am calling Initialize() on Start() and before I try anything with Loom. What am I doing wrong? Thank you

    • Callabrator
      August 15, 2014 - 5:33 pm Reply

      To solve the get_isPlaying issue, make sure you’ve got a Loom.cs script attached to a GameObject in your hierarchy.

  • PranavSathy
    April 18, 2014 - 7:49 pm Reply

    Calling QueueOnMainThread always results in a get_isPlaying can only be done on the main thread issue,
    however I am calling Initialize() on Start() and before I try anything with Loom. What am I doing wrong? Thank you

  • Huacanacha
    May 14, 2014 - 11:51 pm Reply

    I managed to resolve the get_isPlaying error by making a very simple Loom class of my own. It’s a cut down and re-architected version purely for dispatching message to the main thread. It will auto-initialise just by adding it to an object in the scene.

    This makes the Parse.com backend API usable within Unity ;)

    Note: I’m sure there are cases I haven’t thought of here and its not thoroughly tested… so use with caution.

    === Usage ===

    SceneLoom.Loom.QueueOnMainThread(() => {
    Debug.Log(“Hello main thread!”);
    // Your main thread code here
    });

    === SceneLoom.cs ===

    using UnityEngine;
    using System.Collections.Generic;
    using System.Threading;
    using Action=System.Action;

    public class SceneLoom : MonoBehaviour
    {
    public interface ILoom {
    void QueueOnMainThread(Action action);
    }

    private static NullLoom _nullLoom = new NullLoom();
    private static LoomDispatcher _loom;
    public static ILoom Loom {
    get {
    if (_loom != null) {
    return _loom as ILoom;
    }
    return _nullLoom as ILoom;
    }
    }

    void Awake() {
    _loom = new LoomDispatcher();
    }
    void OnDestroy() {
    _loom = null;
    }

    void Update() {
    if (Application.isPlaying) {
    _loom.Update();
    }
    }

    private class NullLoom : ILoom {
    public void QueueOnMainThread(Action action) {}
    }

    private class LoomDispatcher : ILoom {
    private readonly List actions = new List();

    public void QueueOnMainThread(Action action) {
    lock (actions) {
    actions.Add(action);
    }
    }

    public void Update() {
    // Pop the actions from the synchronized list
    Action[] actionsToRun = null;
    lock (actions) {
    actionsToRun = actions.ToArray();
    actions.Clear();
    }

    // Run each action
    foreach (Action action in actionsToRun) {
    action();
    }
    }
    }
    }

  • Lanre
    May 15, 2014 - 3:14 pm Reply

    Good day. This is an awesome tutorial but I wanna ask you if Unity allows your LOOM framework to access it’s classes like Transform. I wish to use your framework to delegate my game’s movement functions (no rigid bodies, just transform.Translate()s ) to another core/thread. So instead of

    function Update() {
    transform.Translate(Speed*Time.deltaTime);
    }

    can I use your framework to do

    Loom.RunAsync(“Movement”);

    where movement is

    function Movement() {
    transform.position += Vector3.forward*Speed*Time.deltaTime;
    }

    I hope so, Im yet to test it

    • whydoidoit
      May 15, 2014 - 4:42 pm Reply

      Sadly not, you can’t access anything Unity from another thread as it would mess up collision etc. you should probably use a coroutine.

  • soimy
    May 22, 2014 - 7:36 pm Reply

    Have I missed something?
    Copy and paste the Loom source from above, save as Loom.cs in asset script folder.
    Just wrote a simple test:

    using UnityEngine;
    using System.Collections;

    public class StartBtn : MonoBehaviour {

    public GUIText debugTXT;
    private string data;

    void Start(){
    var tmp = Loom.Current;
    }
    void OnGUI(){
    if(GUI.Button(new Rect(400, 330 ,120, 50), “Start”)){
    Loom.RunAsync(()=>{
    data += “test”;
    Loom.QueueOnMainThread(()=>{
    debugTXT.text += data + “\n”;
    });
    });
    }
    }
    }

    But what ever I tried to initialize the Loom before ask for queueOnMainThread, it always throw error:

    get_isPlaying can only be called from the main thread. Constructors and field initializers will be executed from the loading thread when loading a scene. Don’t use this function in the constructor or field initializers, instead move initialization code to the Awake or Start function.

    Help needed! Have I missed something?

  • Tam Huynh
    July 16, 2014 - 3:50 am Reply

    Good article!!! Thank you so much!

  • Domarius
    July 24, 2014 - 9:36 pm Reply

    Hey again! Love this script. I’d like your opinion on something;

    I may have say 4 threads running – every now and again, one of the threads will have to do a particular task that the others will need to wait for, before they can all continue again.

    I’m aware that threads that are not doing anything will leave time for the OS to process other threads.

    But I’m worried that the act of continually checking a variable to see if it’s ok to start work again, will actually count as “doing something”, and the OS will have them check as fast as they can, and not leave time for other threads (like my AI, etc.) which is stupid.

    Should I have the threads use some kind of “sleep” command, so they only check every 0.5 seconds? And what would this command be?

    Or is this situation somehow dealt with appropriately by the OS?

    • whydoidoit
      July 25, 2014 - 4:54 am Reply

      It sounds like you should be using a thread synchronisation object – there are a few of these. Thread sync objects are much more efficient than reading a variable because the whole thread stack etc doesn’t get yanked into the CPU presuming the thread wasn’t active on a core.

      If you are waiting because another thread “owns” some resource (by that I mean physical resource, one of your memory structures or whatever) then you could guard it with a “CriticalSection” – though this does mean that only one thread will ever be in that section – which from your question I am not sure of.

      If you are doing a Many Readers but Only One Writer kind of situation (anything can read, but nothing can read if a writer is writing) then you can us a ReaderWriter lock (I think that’s in our Unity version of .NET – they are not too hard to write if for some reason it isn’t)

      The critical section is way easier because its supported directly in C#

      public Object guard = new Object(); //Can be anything which is an object or derived from Object

      void DoSomething() {
      lock(guard) {
      //Only one thread is in here at a time
      }
      }

      void AnotherThread() {
      lock(guard) {
      //This is also only going to have one thread and will also
      //lock out the DoSomething routine
      }
      }


      See this: http://msdn.microsoft.com/en-us/library/ms173179.aspx

      • Domarius
        July 25, 2014 - 10:04 am Reply

        Thanks man – it’s so awesome that you’re active here.

        It’s pretty simple – it’s procedural landscape generation – I have smaller regions of blocks, but they are reading off a larger map structure square. When the player moves far enough, a new “map” has to be generated for the smaller regions to generate their blocks from. If new regions need to be created in front of the player, and they are all depending on the same map – and that map hasn’t been created yet, they all have to just wait.

        My question was about the waiting – if the smaller data structures just have a loop that’s checking if the larger one is “ready” yet (just checking a single variable), over and over – is that going to count as “active”?

        I’m concerned this loop check will cause the OS to get them to check this variable as fast as they can, and waste processing time that could be spent on other threads (like AI, etc.) when in reality, they could just check every 0.5 seconds or something.

      • Domarius
        August 4, 2014 - 10:14 pm Reply

        After careful reading, I think the “WaitHandle” stuff is what I need. Thank you!

  • Callabrator
    August 15, 2014 - 5:17 pm Reply

    It takes quite a lot for me to sign up to a new website and post a comment, but this bit of code is so freakin’ clean, compact, and HELPFUL that I just had to give you props! Incredible. Completely solved my issues dealing with my Parse.com integration causing errors when trying to do GameObject work inside a Parse.com lambda.

    These errors are now gone if I just wrap up my work in a Loom.QueueOnMainThread call:

    “CompareBaseObjectsInternal can only be called from the main thread.
    Constructors and field initializers will be executed from the loading thread when loading a scene.”

    YEY!

    • whydoidoit
      August 16, 2014 - 7:38 am Reply

      Thanks :)

  • vvirehead
    August 17, 2014 - 5:21 pm Reply

    Good tutorial and nice code, but I’m concerned about one thing: creating new thread every RunOnAsync()? What about thread pools and limiting creation overhead? You can have many threads suspended and waiting for task to run – there is no need to create new ones every time. Worse – user can start now like 50 of them – there is no limitation, and doing so would destroy any profit from using multithreading.

Leave a Reply

%d bloggers like this: