This is the fourth day of my participation in the August More text Challenge. For details, see:August is more challenging

Recommended reading

  • CSDN home page
  • GitHub open source address
  • Unity3D plug-in sharing
  • Jane’s address book
  • My personal blog
  • QQ group: 1040082875

One, foreword

  • The main purpose of this article is to explain why foreach loops should be avoided in Unity

  • Did you notice anything wrong with the game?

  • Is it in the loop iteration?

  • Do you often need to iterate through a list of GameObjects?

  • If you have a lot of questions like this, then you’ve come to the right place!

“Usually the problem/is caused by the high level of GC collection in each frame, so before we solve this problem, let’s first understand what GC is.”

What is a garbage collector?

1. Garbage collector (GC) is an important part of any computer device’s memory management system. Its main purpose is to attempt to reclaim or release resources in the system that are no longer used by programs.

2. This is an automated system that ensures that free objects do not occupy memory space, which optimizes memory resources and improves performance. Although it is an automated system, it can be controlled programmatically.

3. In general, the GC must ensure that the object is no longer used in the program before collecting the object.

So how do we use Foreach in Unity

Let’s give an example:

Step1 create a scene in Unity, as shown below:

1. Create a Canvas and a Text as shown in the image above.

2. Create an Empty Gameobject and name it GameObjectList

3. Create some empty objects (about 10-30 will do) and bind them as children of GameObjectList

Step 2 Create a script with any name you want (follow the tutorial if you can) :

I’ll name it foreachLooptest.cs

I prefer C#, but you can use Javascript if you want

   public class ForEachLoopTest : MonoBehaviour

  {

      #region PUBLIC_DECLARATIONS

      public List<GameObject> emptyGameObjects;

      public Text indicatorText;

      #endregion

      #region UNITY_CALLBACKS

      void Update()

      {

          if (Input.GetKeyDown(KeyCode.Space))

          {

              indicatorText.text = "EXECUTION ON";

          }

          if (Input.GetKeyUp(KeyCode.Space))

          {

                indicatorText.text = "HOLD SPACE TO TURN ON EXECUTION";

          }

          if(Input.GetKey(KeyCode.Space)) { UpdateTextValue(); }}#endregion

      #region PUBLIC_METHODS

      public void UpdateTextValue()

      {

        

          foreach (var item in emptyGameObjects)

          {

              // PROCESS ITEMS IN LIST

          }

// for (int i = 0; i < emptyGameObjects .Count; i++)

/ / {

         // PROCESS ITEMS IN LIST

/ /}

     }

     #endregion

}
Copy the code

Note:

Here I annotate the code for the class for loop, leaving only the code for the foreach loop

Step 3 Specify reference and test code To specify reference and test code to follow these steps:

1. Add foreachLoopTest. cs to GameObjectList, specifying all subobject objects in GameObjectList without emptyGameObjects.

2. Now Play the game

3. Open the Profiler Window

Have you noticed a change in Profile?

The value of GC Alloction has not changed? Wonder? What’s going on here?

That’s when you shout… “Hey man, are you wasting our time? I don’t see any changes, except for one number (GC Alloction).”

In this case, you’re right. But now imagine a situation where you have to run 1000 different iterations of the loop, each of which consumes some GC!

This is bound to slow down the CPU on mobile devices, which consumes a lot of processing power dealing with memory allocation management, especially GC (garbage collection).

Now, if you’re not careful and continue to loop through each frame, the program will stall and end, which means your game is bad and the user experience is bad.

It is wise to avoid foreach loops as much as possible.

Ok, maybe you are right after all, but what is the reason behind GC?

You must be curious to know that it’s just a loop! Where is this Object collected from?

First, let’s look at the syntax:

foreach (SomeType s in someList)

  s.DoSomething();
Copy the code

Now compile, the compiler will preprocess the code as follows:

 using (SomeType.Enumerator enumerator = this.someList.GetEnumerator())

{

  while(enumerator.MoveNext()) { SomeType s = (SomeType)enumerator.Current; s.DoSomething(); }}Copy the code

The foreach loop creates an enumerator foreach iteration, and destroys those objects after the iteration. If I use a dictionary or any of these collections.

At this point, the GC recycles the destroyed objects, which consumes a certain amount of CPU performance, resulting in a dull game and a bad mood.

Note:

The number of GCS will depend on the type of traversal of the different collections. In our case, our collection displays as 40B in GC Alloction, but if I use Dicitionary or any other such collection, it will also display differently.

Oh, I get it now!

I hope that’s your exclamation after reading this! If you still don’t get it, then we’ve come to a simple conclusion: Use foreach loops in your game whenever possible.

The last thing I want to say to you is that every little optimization helps us grow.