This is the 8th 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
Make your game ten times faster with a detailed understanding of arrays, lists, and Dictionaries
Goal:
- The main goal of this article: Understand Arrays, Lists, and Dictionaries in great detail to make your game ten times faster.
- Should I use Array? Should I use List? Oh, wait, or Dictionaries?
- Why is my loop taking so long? ?
- I don’t see any errors in my code, so why is my code executing so slowly?
- Why does it take me so long to find the object I want?
- I don’t see any GARBAGE collector processing, so why is my game so delayed?
“These are some of the most common problems we encounter when developing a game.” |
---|
But it’s these common problems that annoy game developers the most!! |
---|
A few milliseconds delay can make a game developer lose their marbles!! |
---|
In the end, we always pass the buck and shout “This is a Unity engine fault, my code is perfect!!” |
---|
Well, that’s not always the case, it’s just that sometimes we don’t use sets in data structures correctly, and we think to ourselves, “Sets are so slow!” |
---|
In an application, we generally manage adjacent object groups in two ways:
1. By creating an Array of objects
2. By creating a collection of objects
We should remember the specific use of each set, its advantages and disadvantages, and know when it is best to use it.
In this article, I’ll list all of the arrays that are commonly used in Unity to help you understand collections better.
What is a set? Collections are special classes for storing and retrieving data. Collections are usually used to dynamically allocate memory for elements, and to access each element in a list by indexing, and so on.
These classes create a collection of objects of class Object. The base class for all data types in C# is the Object class. The main advantage of collections is that they can be dynamically expanded and shrunk in response to application requests.
Collections make the process of memory management and data management quite simple.
So, what are the common collections in Unity? Dictionary and List are the most commonly used sets in Unity. Let me give beginners some basic concepts about Dictionary and List. If you know friends can skip.
1. List
The C#List< T > class represents a powerful List object that is indexed by the List type (which is essentially the generic List class) and can store a collection of objects of no specified type.
It has the same functionality as any collection: Add, Insert, Remove, Search, and so on.
A List has the same index representation as an Array, but its main advantage is to dynamically specify the size of the container.
For example, we can define a List<> of objects like this:
List<GameObject> myListOfGameObjects = new List<GameObject>();
Copy the code
Dictionary actually makes a substitute for the hash table type
A Dictionary represents a key-value pair
For example, if 5 represents Red and 10 represents Green, we would find the Value of Red in the Dictionary by 5 keys.
So if we want to find the Value of Red, just remember the Key 5
So, how does a Dictionary look up data?
For example, we can define a Dictionary object like this:
//Dictionary<int, String>: // In this example, ‘int’ is the key and ‘String’ is the value
Dictionary<int,String> myDictionary = new Dictionary<int, String>();
Copy the code
For now, the main goal of this article is to optimize the use of sets, not to learn about sets, so we’ll ignore the learning of sets.
However, if you want to study it in detail, you can use the following links, which will help you learn the concept of collections in more detail:
-
Msdn.microsoft.com/en-us/libra…
-
www.dotnetperls.com/
-
www.tutorialspoint.com/csharp/csha…
How do collections affect games?
Let’s look at an example and understand how assembly stones affect our game.
1. Set up the scene in Unity as follows
A) Create an Empty Game object and change its name (feel free, in this case I'll call it Test)Copy the code
2. Create a script and name it whatever you like
A) I put here named GenericCollectionsTest. Cs b) I use c # for scripting language, you can also use Javascript, if you want to.Copy the code
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
public class GenericCollectionsTest : MonoBehaviour
{
#region PUBLIC_DECLARATIONS
public int numberOfIterations = 10000000;
#endregion
#region PRIVATE_DECLARATIONS
private Stopwatch stopWatch;
private List<int> intList;
private Dictionary<int.int> intDictionary;
private int[] intArray;
#endregion
#region UNITY_CALLBACKS
void Start()
{
stopWatch = new Stopwatch();
intArray = new int[numberOfIterations];
intList = new List<int> (); intDictionary =new Dictionary<int.int> (); AddFakeValuesInArray(numberOfIterations); AddFakeValuesInList(numberOfIterations); AddFakeValuesInDictionay(numberOfIterations); }void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
PerformTest();
}
if (Input.GetKeyDown(KeyCode.S))
{
SearchInList(111);
SearchInDictionary(numberOfIterations - 1);
UnityEngine.Debug.Log("SearchComplete"); }}#endregion
#region PRIVATE_METHODS
private void AddFakeValuesInArray(int iterations)
{
for (int i = 0; i < iterations; i++)
{
intArray[i] = Random.Range(0.100); }}private void AddFakeValuesInList(int iterations)
{
for (int i = 0; i < iterations; i++)
{
intList.Add(Random.Range(0.100));
}
intList[iterations - 1] = 111;
}
private void AddFakeValuesInDictionay(int iterations)
{
for (int i = 0; i < iterations; i++)
{
intDictionary.Add(i, Random.Range(0.100));
}
intDictionary[iterations - 1] = 111;
}
private void SearchInList(int value)
{
#region FIND_IN_LIST
stopWatch.Start();
int index = intList.FindIndex(item => item == value);
stopWatch.Stop();
UnityEngine.Debug.Log("Index " + index);
UnityEngine.Debug.Log("Time Taken to Find in List "+stopWatch.ElapsedMilliseconds +" ms");
stopWatch.Reset();
#endregion
#region CHECK_IF_CONTAINS_VALUE_IN_LIST
stopWatch.Start();
bool containsValue = intList.Contains(value);
stopWatch.Stop();
UnityEngine.Debug.Log(containsValue);
UnityEngine.Debug.Log("Time Taken To Check in List "+stopWatch.ElapsedMilliseconds +" ms");
stopWatch.Reset();
#endregion
}
private void SearchInDictionary(int key)
{
#region FIND_IN_DICTIONARY_USING_REQUIRED_KEY
stopWatch.Start();
int value = intDictionary[key];
stopWatch.Stop();
UnityEngine.Debug.Log(("Time Taken to Find in Dictionary " + stopWatch.ElapsedMilliseconds + " ms"));
stopWatch.Reset();
#endregion
#region CHECK_IF_DICTIONARY_CONTAINS_VALUE
stopWatch.Start();
bool containsKey = intDictionary.ContainsKey(key);
stopWatch.Stop();
UnityEngine.Debug.Log(containsKey);
UnityEngine.Debug.Log("Time taken to check if it contains key in Dictionary" + stopWatch.ElapsedMilliseconds + " ms");
stopWatch.Reset();
#endregion
}
private void PerformTest()
{
#region ARRAY_ITERATION
stopWatch.Start();
for (int i = 0; i < intArray.Length; i++)
{
}
stopWatch.Stop();
UnityEngine.Debug.Log("Time Taken By Array "+stopWatch.ElapsedMilliseconds + "ms");
stopWatch.Reset();
#endregion
#region LIST_ITERATION
stopWatch.Start();
for (int i = 0; i < intList.Count; i++)
{
}
stopWatch.Stop();
UnityEngine.Debug.Log("Time Taken By List "+stopWatch.ElapsedMilliseconds + "ms");
stopWatch.Reset();
#endregion
#region LIST_ITERATION_BY_FOREACH_LOOP
stopWatch.Start();
foreach (var item in intList)
{
}
stopWatch.Stop();
UnityEngine.Debug.Log("Time Taken By List Using foreach "+stopWatch.ElapsedMilliseconds + "ms");
stopWatch.Reset();
#endregion
#region DICTIONARY_ITERATIOn_LOOP
stopWatch.Start();
foreach (var key in intDictionary.Keys)
{
}
stopWatch.Stop();
UnityEngine.Debug.Log("Time Taken By Dictionary "+stopWatch.ElapsedMilliseconds + "ms");
stopWatch.Reset();
#endregion
}
#endregion
}
Copy the code
3. Break down the code and understand it
A) Let's break down the code and understand the code step by step b) Show some data here, as shown in the following table:Copy the code
intArray | An Array of type int |
intList | A List of int |
intDictionary | A Dictionary with int keys |
C) Now, let's look at the Start() methodCopy the code
void Start()
{
stopWatch = new Stopwatch();
intArray = new int[numberOfIterations];
intList = new List<int> (); intDictionary =new Dictionary<int.int> (); AddFakeValuesInArray(numberOfIterations); AddFakeValuesInList(numberOfIterations); AddFakeValuesInDictionay(numberOfIterations); }Copy the code
D) Here, I initialize an Array, a List, and a Dictionary, and add random values to them. E) As you can see in the code, I created a Private method to add random numbers to those collections. F) HERE I also use the Stopwatch object for time and performance testing, and also initialize it in Start() g) If you don't know how Stopwatch works, it will help you to understand it before going on. H) Please refer to the following links:Copy the code
www.dotnetperls.com/stopwatch
I) Now let's take a look at the PerformTest() method. J) I've divided this method into four pieces, so it's easier to understand:Copy the code
ARRAY_ITERATION | Here we’re just going to iterate through that array |
LIST_ITERATION | Here we just use a simple for loop to traverse the list |
LIST_ITERATION_BY_FOREACH_LOOP | Here we use a foreach loop to iterate through the list |
DICTIONARY_ITERATION_LOOP | Here we go through the dictionary |
K) As you can see in Update(), we call PerformTest() when we press the "Space" key. L) Now, we will execute the project to test it.Copy the code
Note To get exact data on performance, we iterated over 100,000 times for each type of data set. Your output should look like this:
N) So, does that mean Array is the best? Should we just use Array? No, that's not true. As we said before, we need to use collections in a planned way. O) Only we need to clarify our needs and specify the type of collection we need according to our own needs. P) Let's take a look at what kind of collection types we should use under what circumstances.Copy the code
Case 1: The number of objects remains the same throughout the game
· Using List and Dictionary is not appropriate in this case, and obviously the number of objects has not changed. However, why does using a collection cause additional memory and CPU consumption?
· Here, Array is twice as efficient as List.
Case 2: The number of objects in the game is constantly changing
· We know from the above that Array is not dynamically allocated, so obviously I should use List in this case. Because objects are constantly changing, a List is much faster than a Dictionary.
· Lists are used to manage object pools
·List is nearly eight times faster than Dictionary
· Traversing a List using a foreach loop takes nearly three times longer than using a for loop (this is detailed in What You Don’t Know about Foreach).
So does this mean we should stop using dictionaries altogether? No, let’s understand it better with the following example. There are two methods in the code, SearchInList() and SearchInDictionary().
Understand through the following table:
SearchInList() | The first part of the method is to pass a value to the list, and then look for the value in the list. The second part is to determine whether the value exists in the list, and then return the corresponding Boolean value based on the judgment condition |
SeatchInDictionary() | The first part of the method is to find the value of the key that was passed in, and the second part is to find out if there is a specified key in the method by using the ContainsKey() method |
Let’s test this by running the project once and see the output log display after pressing the “S” key while running.
The output will look like this:
As you can see from the figure above, searching with a Dictionary takes almost no time
Therefore, if you need to keep looking for objects throughout the game, it’s wise to use a Dictionary.
Accept it, your game can’t be without a set!
Yes, that’s right. We just need to know what type of collection to use under what circumstances.
The conclusion is simple. There are three basic principles:
1. Do not use List when the number of objects remains the same and when objects need to be looked up frequently.
2. If the object is dynamic and you do not need to look up the object frequently, using List is the best choice.
3. If you need to find things quickly and change objects very little, using Dictionary is the best choice.
4. When the number of objects remains the same, using Array is the best option (self-added)
If you want to learn more, click on the links below to learn:
www.dotnetperls.com/dictionary-…
Answers.unity3d.com/questions/3…