基于列表动态实例化预制c#

基于列表动态实例化预制c#,c#,C#,当玩家有可用的升级时,我试图用预制件填充面板,但是我的当前代码出现错误,并且在控制台中出现以下错误 InvalidOperationException:集合被修改;枚举操作可能无法执行。 以下代码块导致此错误 GameObject currentTable=upgradeTable[upgradeTableLevel-1]; 如果(GameManager.Instance.AvailableUpgrades!=null){ foreach(在GameManager.Instance.Availa

当玩家有可用的升级时,我试图用预制件填充面板,但是我的当前代码出现错误,并且在控制台中出现以下错误

InvalidOperationException:集合被修改;枚举操作可能无法执行。

以下代码块导致此错误

GameObject currentTable=upgradeTable[upgradeTableLevel-1];
如果(GameManager.Instance.AvailableUpgrades!=null){
foreach(在GameManager.Instance.AvailableUpgrades中升级upg){
GameObject go=实例化(UpgradePrefact,currentTable.transform);
go.getComponentChildren().text=upg.ToString()+“(级别:“+GameManager.Instance.upgrades[upg]+”);
go.getComponentChildren().getComponentChildren().text=“购买用于”+GameManager.Instance.GetNextCost(GameManager.Instance.upgrades[upg])。ToString()+“单位”;
GameManager.Instance.DisplayedUpgrades.Add(upg);
GameManager.Instance.AvailableUpgrades.Remove(upg);
}
}
此代码还生成了多个预置

目标行为是在升级可用时用升级填充
列表
“AvailableUpgrades”,这是通过这段代码完成的

public void UpdateAvailableUpgrades(){
foreach(KeyValuePair cur正在升级){
如果(单位>=GetNextCost(当前值)){
如果(!AvailableUpgrades.Contains(cur.Key)&!DisplayedUpgrades.Contains(cur.Key)){
可用等级添加(当前键);
}
}
}
}
升级可用后,将调用此代码块

#地区升级表
int upgradeTableLevel=GameManager.Instance.FetchUpgradeLevel(Upgrade.UpgradeTable);
upgradeTable[upgradeTableLevel-1].SetActive(true);
foreach(游戏对象进入升级表){
如果(go!=upgradeTable[upgradeTableLevel-1]){
go.SetActive(false);
}
}
//待办事项
//添加查找当前活动表的方法,并在其中添加新的升级预置
//临时溶液
GameObject currentTable=upgradeTable[upgradeTableLevel-1];
如果(GameManager.Instance.AvailableUpgrades!=null){
foreach(在GameManager.Instance.AvailableUpgrades中升级upg){
GameObject go=实例化(UpgradePrefact,currentTable.transform);
go.getComponentChildren().text=upg.ToString()+“(级别:“+GameManager.Instance.upgrades[upg]+”);
go.getComponentChildren().getComponentChildren().text=“购买用于”+GameManager.Instance.GetNextCost(GameManager.Instance.upgrades[upg])。ToString()+“单位”;
GameManager.Instance.DisplayedUpgrades.Add(upg);
GameManager.Instance.AvailableUpgrades.Remove(upg);
}
}
#端区
这里发生的事情是,一旦我们开始
//temp solution
我正在抓取当前活动的表,我就会得到表级别(抓取当前活动的表和其他不相关的内容所需)。然后检查
AvailableUpgrades
中是否有任何升级,如果有,我会在列表中循环,为列表中的每个升级实例化一个新的升级预置。在此列表末尾,升级将从
AvailableUpgrades
中删除,并添加到
DisplayedUpgrades
中,我添加了2个列表来处理此问题它不断产生新的预制件,但它仍然在产生它们


那么,如何修复脚本以提供预期的行为呢?

错误解释得很清楚,这里列举的集合

foreach(Upgrade upg in GameManager.Instance.AvailableUpgrades){
 ...
然后在这里修改,它仍然在循环内(枚举)

您只需维护一个要删除的升级列表,然后在循环完成后删除它们。
因此,创建一个新的升级列表,将.Remove更改为将其添加到此新列表中,而不是[upgradesToRemove.add(upg)],然后在循环完成后,您可以从GameManager.Instance.AvailableUpgrades中删除新列表中的所有升级,因为当您在循环之外时,它不再被枚举。Ez.

错误清楚地解释了您在这里枚举的集合

foreach(Upgrade upg in GameManager.Instance.AvailableUpgrades){
 ...
然后在这里修改,它仍然在循环内(枚举)

您只需维护一个要删除的升级列表,然后在循环完成后删除它们。
因此,创建一个新的升级列表,将.Remove更改为将其添加到此新列表中,而不是[upgradesToRemove.add(upg)],然后在循环完成后,您可以从GameManager.Instance.AvailableUpgrades中删除新列表中的所有升级,因为当您在循环之外时,它不再被枚举。Ez.

正如Milney所提到的,
foreach
循环不允许出于安全原因更改正在迭代的枚举。不管怎样,避免这种操作通常是一种很好的做法,因为它很容易导致讨厌的bug。如果您仍希望这样做(正如我自己做过几次一样),您可以使用
for
循环而不是
foreach

for (int i = 0; i < GameManager.Instance.AvailableUpgrades.Count; i++) {
    // Do you thing
    if (/*some possible condition*/) {
        GameManager.Instance.DisplayedUpgrades.Add(/*some new Object*/);
    }
    if (/*another possible condition*/) {
        GameManager.Instance.AvailableUpgrades.RemoveAt(i);
        i--; // Since i is pointing to current object that was just removed
        // Otherwise you'd skip one object
    }
}
for(int i=0;i
我重复一遍这种代码很容易导致难以跟踪的bug,而且对于项目中的新手来说也很难理解,因此建议您尝试