簡體   English   中英

Unity c#中嵌套循環中的StackOverflowException

[英]StackOverflowException in nested loop in Unity c#

在 Unity c# 中,我從 json 獲取數據,我正在使用嵌套循環(如下代碼)查找/比較游戲對象以在本地游戲對象中設置該數據。 但是在獲得一定數量的對象(> 275)后,我收到了 StackOverflowException 錯誤。 基本上 80 次循環運行 10 次,運行 300 次,請參見下面的代碼。(注意:此代碼在較低的數字下運行正常,例如當 j < 275 時)。

public void SetDataInObject()
    {
        if (j < ObjList.objects.Count)  //count is approx 300
        {
            for (int k = 0; k < allObjs.Length; k++)  // Length is 10
            {                
                stCalc = uiMana.floorStats[k].GetComponent<StatesCalc>();

                for (int m = 0; m < allObjs[k].floorObjs.Length; m++)  //Length is 80
                {
                    string serverObj = ObjList.objects[j].name;
                    string localObj = allObjs[k].floorObjs[m].gameObject.name;

                    if (localObj == serverObj)
                    {
                        ObjManager curObjManger = allObjs[k].floorObjs[m].GetComponent<ObjManager>();
                        //Logic to set data in local objects
                    }
                }                
            }
            j++;
            SetDataInObject();
        }
    }

你的內部塊運行大約300 * 10 * 80 = 240000次遞歸,多次存儲一些值,另外需要一些更長的解析以了解那里做了什么。

實際上,我沒有看到您可以在方法中更改ObjList.objects任何地方。

public void SetDataInObjects()
{
    for (var j = 0; j < ObjList.objects.Count; j++)
    {
        // This actually stays the same for all inner iterations until j is changed
        // so keep it around as long as possible to save resources
        var serverObj = ObjList.objects[j].name;

        for (int k = 0; k < allObjs.Length; k++)  // Length is 10
        {                
            stCalc = uiMana.floorStats[k].GetComponent<StatesCalc>();
            // Also this stays the same until k is changed
            // so keep the reference around to save access calls
            var currentObj = allObjs[k];

            for (int m = 0; m < currentObj.floorObjs.Length; m++)  //Length is 80
            {
                var localObj = currentObj.floorObjs[m].gameObject.name;

                if (localObj == serverObj)
                {
                    ObjManager curObjManger = allObjs[k].floorObjs[m].GetComponent<ObjManager>();
                    //Logic to set data in local objects
                }
            }                
        }
    }
}

您存儲的變量是簡單的類型,如intstringComponent引用.. GC 不應該關心什么太復雜。

實際上,在我看來,完全不使用jm索引會更好地解決這個問題

public void SetDataInObjects()
{
    foreach(var serverObj in ObjList.objects)
    {
        var serverName = serverObj.name;

        for (int k = 0; k < allObjs.Length; k++)  // Length is 10
        {                
            stCalc = uiMana.floorStats[k].GetComponent<StatesCalc>();
            // Also this stays the same until k is changed
            // so keep the reference around to save access calls
            var currentObj = allObjs[k];

            foreach (var floorObj in currentObj.floorObjs)  //Length is 80
            {
                if (localObjName.Equals(serverName))
                {
                    var curObjManger = floorObj.GetComponent<ObjManager>();
                    //Logic to set data in local objects
                }
            }                
        }
    }
}

這顯然仍會運行內部塊300 * 10 * 80 = 240000次,但使用在每次迭代后清除的局部變量,因此它們不會增加分配內存。

請注意,仍然重復調用GetComponent是非常昂貴的,如果可能的話,您應該事先存儲引用。

例如,通過將floorStats的類型直接設置為StatesCalc[]並將StatesCalc[]的類型floorObjsObjectManager[] ,假設您通過 Inspector 引用這些,它將自動存儲相應的類型引用,因此在運行時不需要GetComponent

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM