[英]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
}
}
}
}
}
您存儲的變量是簡單的類型,如int
、 string
和Component
引用.. GC 不應該關心什么太復雜。
實際上,在我看來,完全不使用j
和m
索引會更好地解決這個問題
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[]
的類型floorObjs
為ObjectManager[]
,假設您通過 Inspector 引用這些,它將自動存儲相應的類型引用,因此在運行時不需要GetComponent
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.