[英]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.