Unity的优化系列(三):理解数组、 列表和字典的详细

发表于2017-10-11
评论0 2.1k浏览


集合的影响有哪些?

难道应该完全停止使用字典集合么?

总之,几毫秒的缓慢循环都会让玩家发疯!!!(集合都太慢了)   其实在游戏开发中经常会遇到对集合数据的排序:

在应用程序中我们管理相关对象通过以下两种方式之一:

  1. 通过创建对象数组(创建就不变大小)
  2. 通过创建对象的集合(可以动态改变大小)


每一种集合都有特定的用途,都有自己的优点和缺点。

List<GameObject> myListOfGameObjects = new List<GameObject>();  
Dictionary<int, String> myDictionary = new Dictionary<int, String>();  

新建一个脚本 作为测试:

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            //  循环遍历列表中使用简单的 for 循环  
        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             //  遍历列表中通过使用 foreach 循环  
        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  
}  


关于秒表类Stopwatch   ,用于测试函数的执行时间特别方便。    请参阅以下链接 ︰ http://www.dotnetperls.com/stopwatch (注意这个类是官方的API)


运行之后的输出如下:



                       让我们来了解数据结构,我们应该使用 考虑的几例 ︰


      案例 1) 对象的数量保持不变在整个游戏


             显然不会改变对象的数目 现在在这里就不值得用作列表或字典。


             在这里数组的性能列表2 !


      案例 2) 对象的数量在游戏过程中不断变化


             显而易见的选择是列表。作为对象不停地变化,它是字典更快.      如果对象池,列出了常用来管理池。


      列表与词典进行比较几乎是8-10 倍快如果您遍历使用foreach循环List 几乎才会 3 倍的时间比正常的循环,从而增加了使用foreach循环的一个更多缺点上面的示例所示。如果你想要看看其他缺点的foreach循环 


      难道我应该完全停止使用的词典吗?


      字典的查找 索引可是强项:


      SearchInList()方法的第一部分是来查找列表中传递给它的值,检查如果它实际上包含的值,并返回布尔值


       SeatchInDictionary()方法的第一部分是要根据传递给它,键的值和第二部分将检查如果该方法具有特定键或不存在,通过使用ContainsKey() 再次按键调用这些方法的


      在看Log的输出:



                    所以从图片显而易见的结论是,字典搜索时间是几乎为零。 所以每当要不断寻找一些对象在整个游戏的情况下,明智的选择就是选择词典!


                  结论是简单的有三个基本准则 ︰


      1. 当对象数目仍然相同,也有是没有要求的密集搜索不使用列表。
      2. 如果对象是动态和搜索不是一个优先事项,列表!
      3. 快速访问和对象,那么词典将是明智的选择


      如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引

      0个评论