Parallel for Unity (Scripting/Threading)

2973297--220906--Parallel Large.jpg
Asset Store Link

Parallel for Unity can make your games run faster!
*Includes Perlin Noise Example

What is Parallel for Unity?

  • Loops run over x2 faster
  • Unlocks the power of multi-thread CPUs
  • Divides work across multiple threads
  • Executes for/foreach loops in Parallel
  • Executes lambda expressions in Parallel

Why is Parallel for Unity useful?
If you have expensive thread-safe loops you can easily run them in Parallel without writing complex thread management code.

How? Replace:
for(int i = 0; i < max; i++){ … }
Parallel.For(0, max, (i) => { … });

foreach(var item in items) { … }
Parallel.ForEach(items, (item) => { … });

Method1();
Method2();
Parallel.Invoke(
() => Method1(),
() => Method2());

Want an easy way to manage threads?
Task for Unity
Want to spawn objects in Parallel?
Async Objects

On sale for 30% off!

No longer on sale but my other assets are on sale now!
Task for Unity
Async Objects

It’s back on sale!
But only until April 30th, so don’t miss out.

Hello,

Just tested with IEnumerator: and got this error :

error CS1621: The yield statement cannot be used inside anonymous method blocks[/code]

IEnumerator InstantiateHotspots()
        {   
            // Reset Image360 rotation to 0 to prevent wrong hotspot rotation after instantied
            Image360Controller.ResetRotation();
           
            Parallel.For(0, jsonvale["items"].Count, (i)=>
            {
                GameObject newSpot = Instantiate(hotspot, new Vector3(GetFloat(model.PositionX[i].ToString(),0), GetFloat(model.PositionY[i].ToString(),0), GetFloat(model.PositionZ[i].ToString(),0)), Quaternion.identity);
               
                newSpot.transform.SetParent(this.transform);
               
                newSpot.name = model.ID[i].ToString();
               
                if(ApplicationController.currentLanguage == Constants.JSON_NAME_FR)
                    newSpot.GetComponentInChildren<TextMeshProUGUI>().text = model.Name_fr[i].ToString();
                else
                    newSpot.GetComponentInChildren<TextMeshProUGUI>().text = model.Name_en[i].ToString();

                newSpot.SetActive(true);
               
                // Activate selection only when all hostpot finnished animation apparition
                if(i == (jsonvale["items"].Count - 1))
                {
                    animationEnd = true;

                    Image360Controller.RotationForHP();
                   
                    yield return new WaitForSeconds(0.5f);
                   
                    // Reveal hotspot
                    ApplicationController.FadeIn();
                   
                    // Delay hotspot animation apparition
                    var children = new List<GameObject>();
                    float num = .3f;
                    foreach (Transform child in transform) children.Add(child.gameObject);
                    for (int y = 0; y < children.Count; y++)
                    {
                        num = num + .1f;
                        children[y].transform.Rotate(new Vector3(0, -72, 0));
                        children[y].transform.DOScale(new Vector3(1.3f,1.3f,1.3f), .3f).SetDelay(num);
                    }
                }   
                newSpot.transform.GetChild(0).GetComponent<Transform>().localPosition = new Vector3(GetFloat(model.HPtxtPositionX[i].ToString(),0), GetFloat(model.HPtxtPositionY[i].ToString(),0), 0);
            });
        }

How can integrate with in Coroutine ?

Thx

There are 3 issues with what you’re doing.

  • A bunch of that code isn’t thread-safe. You can’t Instantiate or modify Transforms/GameObjects in a separate thread. Async Scheduler can schedule that code on the main thread, however the less thread-safe code is running in parallel the less benefits you get (You won’t benefit from Parallel if all of the code runs through Async). Most C# operations including math are thread-safe, Unity Engine classes are not.

  • The block of code containing the yield statement doesn’t belong in the loop because it only runs once at the end. It could simply be run after the loop.

  • You’re mixing co-routines and threads, if you wanted to add a delay in threads you use Thread.Sleep. But you must run the entire InstantiateHotspots method in a separate thread with Task or native threading.

Thanks for clear explanation, need to refactor my code :slight_smile:

Best,

What is the advantage using these instead the same methods from System.Threading.Tasks?

This was made for .NET 3.5 when .NET 4 functionality such as Tasks wasn’t supported. So I guess it’s only useful if you cannot use .NET 4 or higher

1 Like