Search Unity

Unity Threading Helper

Discussion in 'Assets and Asset Store' started by Marrrk, May 21, 2011.

  1. Marrrk

    Marrrk

    Joined:
    Mar 21, 2011
    Posts:
    1,032
    Unity Threading Helper
    $Fotolia_34453816_XS.jpg
    Hi there,

    for my current Project I have created a little side product and I want to share this little side product with you.

    As the thread title already says i, I created something to help me and you when working with Threads and Unity.

    AssetStore Version (Contains examples)
    The free version (does not contain any examples): View attachment $UnityThreading.zip

    The API reference

    So now the important stuff:

    Why do I want to use it?
    Because Unity is basically not multi thread compatible and does not provide any helper methods or classes for the work with threads. You can of course create everything you need with Mono, but if you want to just use multi threading you can now.

    How do I use it?
    Simply import the package. Now you can use inside your scripts the UnityThreadingHelper class. this class provides a bunch of static methods and properties:
    • UnityThreadingHelper.Dispatcher - tell the MainThread to run a bunch of commands (Unity commands for example)
    • UnityThreadingHelper.TaskDistributor - run a bunch of commands in a free worker thread
    • UnityThreadingHelper.CreateThread - create a new thread which runs the given bunch of commands
    I will go more in detail in the following questions.

    How do I remove it?
    The UnityThreadingHelper will automatically remove every thread when leaving the game mode. But if you want manual control over the life time of the created Threads and Tasks you can call Dispose() on almost every class in this package.

    How do I create a new thread?
    To create a new Thread call one of the 4 versions of UnityThreadHelper.CreateThread:

    2 simple examples:
    Code (csharp):
    1.  
    2. UnityThreading.ActionThread myThread;
    3.  
    4. void Start()
    5. {
    6.   myThread = UnityThreadHelper.CreateThread(DoThreadWork);
    7. }
    8.  
    9. void DoThreadWork()
    10. {
    11.   // processing
    12. }
    13.  
    Code (csharp):
    1.  
    2. UnityThreading.ActionThread myThread;
    3.  
    4. void Start()
    5. {
    6.   myThread = UnityThreadHelper.CreateThread(() =>
    7.   {
    8.     // processing
    9.   });
    10. }
    11.  
    Which version you prefer is up to you :)
    You dont even need to store the return value of CreateThread, the UnityThreadHelper will take care of finished threads. But if you want to maybe send an abort signal to the thread processing method you will need to store it.

    How do I check inside the thread if the thread should abort, and how do I abort it?
    Easy, simply check in your thread function if the ShouldStop property is set to true:

    Code (csharp):
    1.  
    2. void DoThreadWork(UnityThreading.ActionThread thread)
    3. {
    4.   // processing
    5.  
    6.   // check if we should stop
    7.   if (thread.ShouldStop)
    8.     return; // finish
    9.  
    10.   // more processing when we should not stop yet
    11. }
    12.  
    Or:
    Code (csharp):
    1.  
    2. void DoThreadWork()
    3.  {
    4.    // processing
    5.  
    6.   // check if we should stop
    7.   if (UnityThreading.ActionThread.CurrentThread.ShouldStop)
    8.     return; // finish
    9.  
    10.   // more processing when we should not stop yet
    11.  }
    12.  
    And this is how you can signal the thread to stop:

    Code (csharp):
    1.  
    2. myThread.Exit(); // this signals the thread to stop
    3. myThread.Abort(); // this forces the thread to stop and waits until the thread has stopped.
    4. myThread.AbortWaitForSeconds(10.0f); // this forces the thread to stop and waits max. 10 seconds, when its not stopped after this time, the thread will be terminated
    5.  
    A thread will automatically stop when the thread process function leaves.

    How do I call unity commands and methods with it?
    When you need to call something at the MainThread you can make use of the Dispatcher, the Dispatcher is a little class which will be updated each frame and will process all commands it has been send from an other thread. The most easy way to send a command or a bunch of commands into the MainThread is this:

    Code (csharp):
    1.  
    2.  void DoThreadWork()
    3.   {
    4.     // instantiate the asset "enemy"
    5.   UnityThreadHelper.Dispatcher.Dispatch(() => Instantiate(Resources.Load("enemy")));
    6.  
    7.   // or like this:
    8.   var objectToInstantiate = "enemy";
    9.   UnityThreadHelper.Dispatcher.Dispatch(() => Instantiate(Resources.Load(objectToInstantiate)));
    10.  
    11.   // or more like this:
    12.   var health = Mathf.Random(10, 100);
    13.   UnityThreadHelper.Dispatcher.Dispatch(() =>
    14.   {
    15.     var newGameObject = Instantiate(Resources.Load(objectToInstantiate));
    16.     newGameObject.GetComponent<MyComponent>().health = health;
    17.   }
    18.   }
    19.  
    The Dispatch method returns an instance of the Task class, if you want you can use it for example to wait for completion of the dispatched operation:

    Code (csharp):
    1.  
    2. var task = UnityThreadHelper.Dispatcher.Dispatch(...);
    3. task.Wait();
    4.  
    Also a great feature of the Dispatcher is the ability to dispatch not only methods, but also functions:

    Code (csharp):
    1.  
    2. var task = UnityThreadHelper.Dispatcher.Dispatch(() => { return 1+1; });
    3. var result = task.Wait<int>();
    4.  
    Code (csharp):
    1.  
    2. var task = UnityThreadHelper.Dispatcher.Dispatch(() => { return 1+1; });
    3. task.Wait();
    4. var result  = task.Result;
    5.  
    There are many many more features to discover, just throw a look into what IntelliSense displays for you or ask me :)

    How do I create simple background Tasks and why not use a extra thread?
    If you have many sub operations you dont want to create an extra thread, every thread created will lower the overall performance of the process and will also take some time to be created (noticeable when you create many threads).

    Simple background tasks dispatched by the TaskDistributor class will allow a very large amount of tasks to be processed without the need of the creation of many extra threads.

    To use the TaskDistributor just call UnityThreadHelper.TaskDistributor and use the instance like a Dispatcher:

    Code (csharp):
    1.  
    2. UnityThreadHelper.TaskDistributor.Dispatch(...);
    3.  
    It works exactly like the Dispatcher with the difference that every task will be processed in the background. The current implementation of the TaskDistributor allows up to ProcessorCount multiplied by 3 parallel tasks to be operated. Dont worry, if you dispatch more than this amount, the tasks will be processed at the time the amount is below this value.

    Questions, comments, encouraging love letters, everything is welcome :)

    AssetStore Version
    Basic version: View attachment $UnityThreading.zip
     
    Last edited: Feb 14, 2014
  2. CorruptScanline

    CorruptScanline

    Joined:
    Mar 26, 2009
    Posts:
    217
    Cool, looks very useful. Does it work the same in unityscript?
     
  3. Marrrk

    Marrrk

    Joined:
    Mar 21, 2011
    Posts:
    1,032
    I am no UnityScript coder, but it should work there too, the only difference will be the usage of anonymous functions

    C#
    Code (csharp):
    1.  
    2. () =>
    3. {
    4.   // Do something
    5. }
    6.  
    UnityScript
    Code (csharp):
    1.  
    2. function()
    3. {
    4.   // Do something
    5. }
    6.  
    Someone with more UnityScript experience than me should test this. (I would test it but I am not on a Unity capable system right now).
     
  4. sebako

    sebako

    Joined:
    Jun 27, 2009
    Posts:
    298
    Hmm looks nice - I will give it a try. Thanks for sharing :)
     
  5. Marrrk

    Marrrk

    Joined:
    Mar 21, 2011
    Posts:
    1,032
    I write a system which allows you to call Unity methods without the need of a Dispatcher call (at least you dont need to call it, under the hood its still done). Tell me what you think.

    Example for static methods (unfortunately there are no static extension methods in the current C# version):
    Code (csharp):
    1.  
    2. using UnityThreadingExtensions
    3. ...
    4.  
    5. void DoThreadWork()
    6. {
    7.     ...
    8.     AssetStoreMT.SaveWait();
    9.     AssetStoreMT.RefreshWait();
    10. }
    11.  
    Sample for instance methods:
    Code (csharp):
    1.  
    2. using UnityThreadingExtensions
    3. ...
    4.  
    5. void DoThreadWork()
    6. {
    7.     ..
    8.     var myComponent = myGameObject.GetComponentMTWait<MyComponent>();
    9.     myComponent.DoSomethingMT();
    10.     myComponent.DoModeMT();
    11.     myComponent.CalcPiMT();
    12.     myComponent.AngerBadPeopleMT();
    13. }
    14.  
    Basically I extend the unity classes (and also your classes if you run a little helper tool to create the neccessary stuff) about 2 methods for each original method.

    Generated sample script:
    Code (csharp):
    1.  
    2. namespace UnityThreadingExtensions
    3. {
    4.     public static class TestClassMT
    5.     {
    6.         #region StaticMethods
    7.  
    8.         public static TaskBase StaticTest<T, U>(T a, U b)
    9.         {
    10.             return Dispatcher.Main.Dispatch(() => { TestClass.StaticTest<T, U>(a, b); });
    11.         }
    12.  
    13.         public static void StaticTestWait<T, U>(T a, U b)
    14.         {
    15.             Dispatcher.Main.Dispatch(() => { TestClass.StaticTest<T, U>(a, b); }).Wait();
    16.         }
    17.  
    18.         public static TaskBase StaticTest()
    19.         {
    20.             return Dispatcher.Main.Dispatch(() => { TestClass.StaticTest(); });
    21.         }
    22.  
    23.         public static void StaticTestWait()
    24.         {
    25.             Dispatcher.Main.Dispatch(() => { TestClass.StaticTest(); }).Wait();
    26.         }
    27.  
    28.         #endregion StaticMethods
    29.  
    30.         #region Methods
    31.  
    32.         public static TaskBase GenericTestMT<T>(this TestClass _TestClass, Int32 a)
    33.         {
    34.             return Dispatcher.Main.Dispatch(() => { _TestClass.GenericTest<T>(a); });
    35.         }
    36.  
    37.         public static T GenericTestMTWait<T>(this TestClass _TestClass, Int32 a)
    38.         {
    39.             return Dispatcher.Main.Dispatch(() => { return _TestClass.GenericTest<T>(a); }).Wait<T>();
    40.         }
    41.  
    42.         public static TaskBase RefTestMT(this TestClass _TestClass, String a, ref Boolean b)
    43.         {
    44.             return Dispatcher.Main.Dispatch(() => { _TestClass.RefTest(a, ref b); });
    45.         }
    46.  
    47.         public static void RefTestMTWait(this TestClass _TestClass, String a, ref Boolean b)
    48.         {
    49.             Dispatcher.Main.Dispatch(() => { _TestClass.RefTest(a, ref b); }).Wait();
    50.         }
    51.  
    52.         public static TaskBase OutTestMT(this TestClass _TestClass, out Boolean a)
    53.         {
    54.             a = default(Boolean);
    55.             return Dispatcher.Main.Dispatch(() => { _TestClass.OutTest(out a); });
    56.         }
    57.  
    58.         public static void OutTestMTWait(this TestClass _TestClass, out Boolean a)
    59.         {
    60.             a = default(Boolean);
    61.             Dispatcher.Main.Dispatch(() => { _TestClass.OutTest(out a); }).Wait();
    62.         }
    63.  
    64.         #endregion Methods
    65.     }
    66. }
    67.  
    Original class:
    Code (csharp):
    1.  
    2. public sealed class TestClass
    3. {
    4.     public static void StaticTest<T, U>(T a, U b) { }
    5.     public static void StaticTest() { }
    6.     public T GenericTest<T>(int a) { return default(T); }
    7.     public void RefTest(string a, ref bool b) {}
    8.     public void OutTest(out bool a) { a = true; }
    9. }
    10.  
    There will be a method with MT as postfix which will not block the calling thread and returns a Task class (see above). Using this would be good in situations in which you want to process these methods without the thread to wait for completion.

    And there will be a method with MTWait as postfix, this will block the thread execution until the main thread executed the method. Also MTWait methods will return the return value of the original method so that you can depend other operations on this.

    So what do you think?
     
    Last edited: May 24, 2011
  6. HarvesteR

    HarvesteR

    Joined:
    May 22, 2009
    Posts:
    495
    This seems very very useful... I wish I knew more about threading in general ;)

    Thankfully you've provided a good deal of usage examples, so I'll try later on to integrate that into my project... drawing procedural terrain is no mean task for a single core... and those coroutines are driving me crazy...

    Thanks for sharing it with the community!!

    Cheers
     
  7. Tinus

    Tinus

    Joined:
    Apr 6, 2009
    Posts:
    431
    Oh my, exactly what I was looking for! There's so many applications for this.. Many thanks for sharing this, it would've taken me ages to figure out this stuff myself as I'm not really familiar with threading. :)

    As for the NameMT classes and methods, I'll have to play around a bit. My first instinct is that I'd rather use the dispatcher calls explicitly, and I don't like it when my namespaces suddenly get twice as big. But if in use it turns out that explicit dispatcher calls are cumbersome to use then I'd gladly use the MT style.

    Thanks for sharing this!
     
    Last edited: May 27, 2011
  8. smh1988

    smh1988

    Joined:
    Jun 8, 2011
    Posts:
    3
    it's so good to have such an ability in unity !
     
  9. jlethbridge

    jlethbridge

    Joined:
    Nov 1, 2010
    Posts:
    28
    This is a super handy package - thanks Marrrk!

    I'm using it in UnityScript now and it's working great. As expected with threading, Unity functions break, but they can often be moved or replaced by the .NET equivalent.

    A note for UnityScript users on this however:

    You'll need to place the Threading folder the package extracts, into either the Standard Assets, Pro Standard Assets or Plugins folder. Because it's in C# and we're using another language to access the namespace, the threading scripts need to be compiled first.

    More detail:
    http://unity3d.com/support/documentation/ScriptReference/index.Script_compilation_28Advanced29.html
    and
    http://answers.unity3d.com/questions/10856/cant-find-namespace-accessing-javascript-from-c-or.html

    Once that's done you can declare the thread variable for use as follows:

    Code (csharp):
    1. var myThread : UnityThreading.ActionThread;
    And calling it...

    Code (csharp):
    1. myThread = UnityThreadHelper.CreateThread(myFunction)
    Once again, brilliant work Marrrk!
     
  10. Marrrk

    Marrrk

    Joined:
    Mar 21, 2011
    Posts:
    1,032
    Good to see that its used :D
     
  11. 95KillerZ95

    95KillerZ95

    Joined:
    May 27, 2011
    Posts:
    253
    Wow, thanks for sharing this... It looks very useful :D
     
  12. Alesk

    Alesk

    Joined:
    Jul 15, 2010
    Posts:
    265
    Hi,

    I'm a new comer to Unity and would like to use this package in a C# class I'm working on, but I'm not sure of the syntax to use it the right way...
    I would like to execute a given function (with different parameters) on 2 or 3 threads simutaneoulsy and then wait for each threads to finish it's work to continue the main code execution.
    This function will modify data at different points in an array, so I'd like to use threads to process the array faster.

    How should I write this properly in C# ?
     
    Last edited: Jun 11, 2011
  13. Marrrk

    Marrrk

    Joined:
    Mar 21, 2011
    Posts:
    1,032
    Not sure if I did understand you correctly, so correct me if I am wrong:

    Code (csharp):
    1.  
    2. int[] myArray = new int[300];
    3. ..
    4. void Foo(int a, int b)
    5. {
    6.   .. // do something with myArray[a] to myArray[b - 1]
    7. }
    8.  
    9. void Start()
    10. {
    11.   var task1 = UnityThreadHelper.TaskDistributor.Dispatch(() => Foo(0, 100));
    12.   var task2 = UnityThreadHelper.TaskDistributor.Dispatch(() => Foo(100, 200));
    13.   var task3 = UnityThreadHelper.TaskDistributor.Dispatch(() => Foo(200, 300));
    14.  
    15.   // Wait for completion
    16.   task1.Wait();
    17.   task2.Wait();
    18.   task3.Wait();
    19. }
    20.  
    This will of course block the main thread execution until all 3 tasks have been completed.

    If you dont want to block the main thread you can do something like this:


    Code (csharp):
    1.  
    2. List<UnityThreading.Task> pendingTasks = new List<UnityThreading.Task>();
    3. int[] myArray = new int[300];
    4. ..
    5. void Foo(int a, int b)
    6. {
    7.   .. // do something with myArray[a] to myArray[b - 1]
    8. }
    9.  
    10. void Start()
    11. {
    12.   for (int i = 0; i < 3; ++i)
    13.     pendingTasks.Add(UnityThreadHelper.TaskDistributor.Dispatch(() => Foo(i * 100, i * 100 + 100)))
    14. }
    15.  
    16. void Update()
    17. {
    18.   // needs System.Linq;
    19.   if (pendingTasks.All(task => task.IsFinished))
    20.     CalculationFinished();
    21. }
    22.  
    23. void CalculationFinished()
    24. {
    25.   pendingTasks.Clear();
    26.   ...
    27. }
    28.  

    If you want to access the same element in different threads remember to lock the access to avoid race conditions, or separate the working data from each thread:

    Code (csharp):
    1.  
    2. List<UnityThreading.Task<int[]>> pendingTasks = new List<UnityThreading.Task<int[]>>();
    3. int[] myArray = new int[300];
    4. ..
    5. int[] Foo(int[] isolatedArray)
    6. {
    7.   .. // do something with isolatedArraY
    8.   return isolatedArray; // or the process result
    9. }
    10.  
    11. void Start()
    12. {
    13.   // needs System.Linq;
    14.   for (int i = 0; i < 3; ++i)
    15.     pendingTasks.Add(UnityThreadHelper.TaskDistributor.Dispatch(() => Foo(myArray.Skip(i * 100).Take(100).ToArray()));
    16. }
    17.  
    18. void Update()
    19. {
    20.   // needs System.Linq;
    21.   if (pendingTasks.All(task => task.IsFinished))
    22.     CalculationFinished();
    23. }
    24.  
    25. void CalculationFinished()
    26. {
    27.   myArray = pendingTasks.SelectMany(task => task.Result).ToArray();
    28.   pendingTasks.Clear();
    29.   ...
    30. }
    31.  

    Hope the code was correct, I wrote that without any reference or IDE near me ;)
     
    Last edited: Jun 11, 2011
  14. Alesk

    Alesk

    Joined:
    Jul 15, 2010
    Posts:
    265
    Hi,

    thanks for the sample code. I've tried your first example, but it looks like it's blocking the code execution forever.
    I want to block the main thread execution only while the foo() function is working, and then restart it as soon as all are completed.
    What is waiting the task.wait() function for, exactly ?

    Also, should I create the task every game loop, or you I create them once, and reuse them all the time ?

    [EDIT] ok forget it, I had an error in the foo() function wich was causing the freeze, but since it was in the thread, no error message was displayed
    it's now working properly :)

    Thank you !
     
    Last edited: Jun 11, 2011
  15. SpiderPork

    SpiderPork

    Joined:
    Jan 29, 2011
    Posts:
    27
    Hey, great helper, but I've only got one problem:

    Every time I use the Dispatcher, I get this error:
    What should I do?

    Thanks
     
  16. rockysam888

    rockysam888

    Joined:
    Jul 28, 2009
    Posts:
    650
  17. Marrrk

    Marrrk

    Joined:
    Mar 21, 2011
    Posts:
    1,032
    Try to use UnityThreadHelper.Dispatcher.Dispatch(...)

    I made a mistake while writing the little introduction code in the start post.
     
  18. Benjamin.Breeg

    Benjamin.Breeg

    Joined:
    Jun 8, 2011
    Posts:
    5
    Thanks to share this code. It helps me a lot !!!
     
  19. hima

    hima

    Joined:
    Oct 1, 2010
    Posts:
    183
    This look interesting but can someone please help give me an example of what are the applications or benefits of using Thread in Unity? How is it different from Invoke and InvokeRepeating?
     
    Last edited: Jun 27, 2011
  20. Marrrk

    Marrrk

    Joined:
    Mar 21, 2011
    Posts:
    1,032
    Invoke and InvokeRepeating are based upon Coroutines, which basically means that the invoked operation is run in the mainthrread with no benefit of multithreading at all. Speak, the operation will block the mainthread until completion.
     
    twobob likes this.
  21. tylo

    tylo

    Joined:
    Dec 7, 2009
    Posts:
    121
    I've done some work with Coroutines and some minor work with threads back in University. Am I right is saying that you will notice performance increases when you try to do heavy computational tasks in threads, but you might not notice any performance difference if your code can run pretty fast as a Coroutine?

    In other words, many instance of "parallelism" can be accomplished with Coroutines still, but threading is useful for stuff that is going to block the hell out of your main Unity loop.
     
  22. Marrrk

    Marrrk

    Joined:
    Mar 21, 2011
    Posts:
    1,032
    When your code runs pretty fast as a coroutine, why invoke it to the mainthread? It will be executed at least the next frame in the mainthread, invoking something makes only sense when you want to execute it some time later or when you want to split a operation up between multiple frames ;)

    But what you wrote makes fully sense, yes.
     
  23. 95KillerZ95

    95KillerZ95

    Joined:
    May 27, 2011
    Posts:
    253
    It works very well! Thanks so much mate!
     
  24. floky

    floky

    Joined:
    Oct 6, 2010
    Posts:
    232
    Awesome work Marrrk! Really awesome!

    One question buddy! Do you know if I could use your threading library to wait for a WWW request to complete?
    Ok it doesn't sound good.
    Take a look at this thread my friend:
    http://forum.unity3d.com/threads/97...et-bundle-BLOCK-main-thread-until-file-loaded

    I need the main thread to block when waiting for WWW request to complete. (WWW request is done in a separate thread)
    And I was wondering maybe if I could somehow do the waiting for a WWW request on a separate thread X using your library and making this separate thread X Join(...) with the main thread so that the main thread waits for X thread to complete (thus waiting for the WWW request to complete)

    I'm trying to do a hack to make the WWW request block until it finishes loading an asset bundle. I have to do this hack to correct a bad code design issue and this would be the fastest way to do it to keep the entire code flow the same.

    Bear in mind that I can't use coroutines because there is a lot of code used in static methods that can't be easily modified without affecting the entire project. :(

    Can you help me with some advice?
     
    Last edited: Jul 22, 2011
  25. Marrrk

    Marrrk

    Joined:
    Mar 21, 2011
    Posts:
    1,032
    As far as I can tell from the link you provided, the WWW class needs to be processed by Unity, something you have no influence on. By blocking the main thread, Unity is not able to handle the WWW class instance which is working/downloading something.
     
  26. floky

    floky

    Joined:
    Oct 6, 2010
    Posts:
    232
    You are right my friend. It seems I am without a quick solution to that problem.
    Thank you for your time.
     
  27. Dantus

    Dantus

    Joined:
    Oct 21, 2009
    Posts:
    5,667
    Marrrk, that is awesome! As I would like to use it, my question is if there are any restrictions for me to use the code?
     
  28. Marrrk

    Marrrk

    Joined:
    Mar 21, 2011
    Posts:
    1,032
    @Dantus: No restrictions, maybe you could mention me somewhere, but this is optional. Do whatever you want with the code :)
     
  29. Dantus

    Dantus

    Joined:
    Oct 21, 2009
    Posts:
    5,667
    That is fantastic!
     
  30. AnomalusUndrdog

    AnomalusUndrdog

    Joined:
    Jul 3, 2009
    Posts:
    1,486
    How do I properly get the return value of Unity code done in UnityThreadHelper.Dispatcher.Dispatch?
     
  31. Marrrk

    Marrrk

    Joined:
    Mar 21, 2011
    Posts:
    1,032
    anomalous_underdog:

    I simply copy from my start post :)

    So, just return the return value of an unity method :)
     
  32. unity_sg

    unity_sg

    Joined:
    Sep 14, 2010
    Posts:
    95
    Hi, thanks for sharing.
    I try to use this package but it don't seems to work, I can't see any difference between this method and the same script and a simple update void.
    I try it with this simple c# script :

    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class updateCollider : MonoBehaviour {
    5.  
    6.   UnityThreading.ActionThread myThread;
    7.  
    8.   void Update () {
    9.    myThread = UnityThreadHelper.CreateThread(DoThreadWork);
    10.   }
    11.  
    12.   void DoThreadWork() {
    13.    UnityThreadHelper.Dispatcher.Dispatch(() => transform.GetComponent<MeshCollider>().sharedMesh = null);
    14.    UnityThreadHelper.Dispatcher.Dispatch(() => transform.GetComponent<MeshCollider>().sharedMesh = transform.GetComponent<MeshFilter>().mesh);    
    15.   }
    16. }
    17.  
    Can you maybe help me please ?
     
    Last edited: Oct 11, 2011
  33. Marrrk

    Marrrk

    Joined:
    Mar 21, 2011
    Posts:
    1,032
    Hi seb7000, you realize that you exactly the same thing as in a plain Update function?

    The Dispatcher.Dispatch call will only tell the main loop (where the plain old Update method is called) to execute the code you give to the dispatcher.

    The Dispatcher will transfer the workload to the thread associated with the Dispatcher instance you are using. In This case the associated thread is the main thread. All (well most of them) Unity methods and objects need to be executed in the mainthread. The Dispatcher only ensures that you can do that inside of an other thread.

    Also du you realize that you create a new thread everytime the Update method is called? This is a significant performance overhead, also the number of allowed threads per process is restricted (dont know the exact numbers). So it may crash after a while for 2 reasons:
    - the max number of threads is reached
    - unity is unable to respond because 1.0000.0000 Threads try to run (threadswitches cost computation time)

    In your sample it should not occour as, your threads will stop after completing the work. But you should reconsider to only create one thread and reuse that. Or use the TaskDistributor which will perform a single action in one background worker thread.

    Oh and one more thing, you can perform multiple actions inside of one Dispatcher call by simply using something like that:
    Code (csharp):
    1. [FONT=monospace]
    2. [/FONT]UnityThreadHelper.Dispatcher.Dispatch(() => [FONT=monospace]
    3. [/FONT]{
    4.   transform.GetComponent<MeshCollider>().sharedMesh = null;[FONT=monospace]
    5. [/FONT]  transform.GetComponent<MeshCollider>().sharedMesh = transform.GetComponent<MeshFilter>().mesh;[FONT=monospace]
    6. [/FONT]});
    7. [FONT=Helvetica][/FONT]
    Can you tell me what you try to archive?
     
  34. unity_sg

    unity_sg

    Joined:
    Sep 14, 2010
    Posts:
    95
    Hi, thanks for anserwing ;)
    For the moment I want to try tour script with a simple example.
    I know that updating a meshCollider use a lot of performance of the computer, so I thinked that was a good example.
    Per example I use this script :

    Code (csharp):
    1.  
    2. void Update
    3. {
    4.   transform.GetComponent<MeshCollider>().sharedMesh = null;
    5.   transform.GetComponent<MeshCollider>().sharedMesh = transform.GetComponent<MeshFilter>().mesh;
    6. }
    7.  
    How can I use your script to optimize it ?
    Thanks
     
    Last edited: Oct 12, 2011
  35. Marrrk

    Marrrk

    Joined:
    Mar 21, 2011
    Posts:
    1,032
    You cant. Its Unity stuff, there is no way to improve this with the help of threading (except when the Unitydevelopers decide to change this).

    What you can do is to generate a meshcollider mesh in a background thread and then use this generated mesh in the mainthread.
    (You need to have an own mesh class for this, as the unity mesh class may not be multithreading compatible and thus cannot be used inside a non mainthread.)
     
  36. unity_sg

    unity_sg

    Joined:
    Sep 14, 2010
    Posts:
    95
    Ok, I understand.
    Can you maybe give us a concret example of using your script ?
     
  37. Marrrk

    Marrrk

    Joined:
    Mar 21, 2011
    Posts:
    1,032
    What do you want to see in such example?
     
  38. Ted-Chirvasiu

    Ted-Chirvasiu

    Joined:
    Sep 7, 2010
    Posts:
    381
    This looks very verry handy!But can you give us a little example of how to use the dispacher in unityscript (JavaScript),since i am very lost,please!

    Code (csharp):
    1.  
    2. I can't figure out how to put that () => { //Function }; to JavaScript...
    3.  
    4. function()
    5. {
    6.  // Do something
    7. }
    8. //---Doesn't work... :(
    9.  
    10.  
    Thanks!
     
    Last edited: Oct 29, 2011
  39. Marrrk

    Marrrk

    Joined:
    Mar 21, 2011
    Posts:
    1,032
    This will not work?

    Code (csharp):
    1. [FONT=monospace]
    2. [/FONT]UnityThreadHelper.Dispatcher.Dispatch(function() { /* do something*/ });[FONT=monospace]
    3. [/FONT]
     
  40. Ted-Chirvasiu

    Ted-Chirvasiu

    Joined:
    Sep 7, 2010
    Posts:
    381
    Aw,i had an error inside the function i was dispaching.Thanks!Amazing scripts!Works perfectly!
     
  41. Ted-Chirvasiu

    Ted-Chirvasiu

    Joined:
    Sep 7, 2010
    Posts:
    381
    Well,what it actually made it work was calling it like this :

    Code (csharp):
    1.  
    2.  
    3.  
    4. function myThread(){
    5.  
    6. //print("New Th");
    7.  
    8. UnityThreadHelper.Dispatcher.Dispatch(Hey);
    9.  
    10. }
    11.  
    12. function Hey(){
    13.  
    14. //Call Unity Stuff
    15.  
    16. }
    17.  
    18.  
    19.  

    I have another question : How can i make the thread sleep?MyThread.Sleep(1) won't work anymore because it sais that it is not a member of UnityThreading.ActionThread;

    Please help me!

    Thanks!
     
  42. Marrrk

    Marrrk

    Joined:
    Mar 21, 2011
    Posts:
    1,032
  43. unisip

    unisip

    Joined:
    Sep 15, 2010
    Posts:
    269
    Great stuff! Will try it as soon as i get a moment.
    I see you're using instantiation in your first examples --> very interesting, since instantiation is definitely a cause for framerate hickups, especially when instantiating large assetbundles.
    Anyway, my question is: from your experience using multi threading in unity, did you find that it reduced fps hickups significantly on things like instantiation, texture loading/compressing and such 'heavy workload' features?
     
  44. Marrrk

    Marrrk

    Joined:
    Mar 21, 2011
    Posts:
    1,032
    Thats all Unity stuff, all I do in my examples is telling the MainThread to execute some stuff, thats everything the dispatcher does.
    Instantiating, eg. is NOT done in an separate thread.

    But(!) it can reduce the hickups like Coroutines can reduce hickups by performing the workkload over several frames.
     
  45. NG*

    NG*

    Joined:
    Oct 31, 2011
    Posts:
    6
    This looks awesome, was thinking of developing something similar myself but this is way better than anything I could come up with :)

    Sorry if this has been said before but whats your stance regarding using it in commercial games? TIA
     
  46. Marrrk

    Marrrk

    Joined:
    Mar 21, 2011
    Posts:
    1,032
    You can use it without limitations, but it would be nice if you mention me or something like that, but thats not needed.
     
  47. NG*

    NG*

    Joined:
    Oct 31, 2011
    Posts:
    6
    No problem, just PM me whatever website/company/whatever you want in the credits
     
    Last edited: Nov 7, 2011
  48. Michael-Ryan

    Michael-Ryan

    Joined:
    Apr 10, 2009
    Posts:
    142
    Does this multi-threading work on iOS devices?
     
  49. thinksquirrel_lily

    thinksquirrel_lily

    Joined:
    Feb 8, 2011
    Posts:
    1,172
    It works well on my iPad 2 here.
     
  50. KHopcraft

    KHopcraft

    Joined:
    Jun 6, 2009
    Posts:
    3,246
    Thanks for this, this will help me greatly.