我正在使用XNA库为C#开发一个简单的游戏.在下面的代码片段中,我得到了
收集被修改; 枚举操作可能无法执行.
第二个foreach循环顶部的错误.在我(相对有限的)C#体验中,这在尝试在循环期间修改底层集合时会发生.但是,据我所知,我没有以任何方式修改enemy_positions集合.此代码中的所有集合都属于此类型List<Vector2>.
这里发生了什么?
//defines collision behaviour when enemy is hit
int be_no = 0;
List<Vector2> tmp_bullets = bullet_i_position;
List<Vector2> tmp_enemy = enemy_positions;
foreach (Vector2 bullet in bullet_i_position)
{
//get bullet collision box
Rectangle bullet_col = new Rectangle(Convert.ToInt32(bullet.X - 12), Convert.ToInt32(bullet.Y - 12), 25, 26);
int en_no = 0;
foreach (Vector2 enemy in enemy_positions)
{
//get enemy collsion box
en_box = new Rectangle(Convert.ToInt32(enemy.X), Convert.ToInt32(enemy.Y), 75, 75);
if (temp_r.Intersects(en_box))
{
//remove all colliding elements
tmp_enemy.RemoveAt(en_no);
tmp_bullets.RemoveAt(be_no);
bullet_direction.RemoveAt(be_no);
}
en_no++;
}
be_no++;
}
//update actual lists
bullet_i_position = tmp_bullets;
enemy_positions = tmp_enemy;
Run Code Online (Sandbox Code Playgroud)
线条:
List<Vector2> tmp_bullets = bullet_i_position;
List<Vector2> tmp_enemy = enemy_positions;
Run Code Online (Sandbox Code Playgroud)
他们没有克隆列表,只是创建了对同一列表的本地引用.直接的解决方案是将这两行更改为:
List<Vector2> tmp_bullets = new List<Vector2>(bullet_i_position);
List<Vector2> tmp_enemy = new List<Vector2>(enemy_positions);
Run Code Online (Sandbox Code Playgroud)
但是每次调用这个方法时都会分配一个新列表,这对于垃圾收集来说会很糟糕(特别是在游戏中),所以更好的解决方案是删除你的foreach循环并用reverse for循环替换它们.这是有效的,因为在使用枚举器迭代集合时,您只会获得该异常.同样的问题不适用于常规for循环.例如:
for (int i = bullet_i_position.Count - 1; i >= 0; i--)
{
Vector2 bullet = bullet_i_position[i];
// ...
}
Run Code Online (Sandbox Code Playgroud)
反向迭代的原因是在定期迭代时删除元素意味着您将在删除元素之后跳过元素(因为索引向下移动1)