Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/298.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何解决无效操作异常?_C#_Arrays_Unity3d - Fatal编程技术网

C# 如何解决无效操作异常?

C# 如何解决无效操作异常?,c#,arrays,unity3d,C#,Arrays,Unity3d,在我的Unity项目中,我有一个LevelGenerator创建Stages(游戏对象)并将其添加到列表中。当我临终时,我想销毁并删除列表中的所有项目。但当我在列表中迭代时,只有第一个对象被销毁并删除,然后发生错误: InvalidOperationException:集合已修改;枚举操作可能无法执行。 System.ThrowHelper.ThrowInvalidOperationException(System.ExceptionResource)(位于:0) System.Collecti

在我的Unity项目中,我有一个
LevelGenerator
创建
Stages
(游戏对象)并将其添加到列表中。当我临终时,我想销毁并删除列表中的所有项目。但当我在列表中迭代时,只有第一个对象被销毁并删除,然后发生错误:

InvalidOperationException:集合已修改;枚举操作可能无法执行。
System.ThrowHelper.ThrowInvalidOperationException(System.ExceptionResource)(位于:0)
System.Collections.Generic.List
1+枚举数[T].MoveNextRare()(at:0)System.Collections.Generic.List
1+枚举数[T].MoveNext()(at:0)

你能帮我吗

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class LevelGenerator : MonoBehaviour
{
    private const float PLAYER_DISTANCE_SPAWN_LEVEL_PART  = 25f;

    [SerializeField] private Transform Startingstage;
    [SerializeField] private List<Transform> StageList;
    [SerializeField] private Transform player;

    public List<GameObject> gameObjectsToDestroy;
    public bool creatingGoesOn = false;

    private Vector3 lastEndPosition;

    public void CreateEnviroment()  // Every time called when game is started
    {
        lastEndPosition = Startingstage.Find("EndingPoint").position;

        int startingSpawnLevelParts = 7;

        for (int i = 0; i < startingSpawnLevelParts; i++)
        {
            SpawnLevelPart();
        }

        creatingGoesOn = true;
    }

    private void Update()
    {
        if (creatingGoesOn)
        {
            if (Vector3.Distance(player.position, lastEndPosition) < PLAYER_DISTANCE_SPAWN_LEVEL_PART)
            {
                // Spawn a new level part if player is to close to the end.
                SpawnLevelPart();
            }
        }
    }

    private void SpawnLevelPart()
    {
        Transform randomStage = StageList[Random.Range(0, StageList.Count)];
        Transform lastLevelPartTransform = SpawnLevelPart(randomStage, lastEndPosition);
        lastEndPosition = lastLevelPartTransform.Find("EndingPoint").position;
    }

    private Transform SpawnLevelPart(Transform stage, Vector3 spawnPosition)
    {
        Transform levelPartTransform = Instantiate(stage, spawnPosition,  Quaternion.identity);
        gameObjectsToDestroy.Add(levelPartTransform.gameObject);
        return levelPartTransform;
    }
}

只要您看到
invalidoOperationException:Collection被修改;枚举操作可能不会执行
,如果在单个线程上访问相关集合,则您应该知道这是因为您正在修改要迭代的相同列表

这通常发生在使用使用
IEnumerable
的功能时,例如:

  • foreach
    循环与您的情况相同
  • GetEnumerator()

循环中常见的解决方案是考虑一个对你的问题有意义的不同结构。


如果需要,我还可以提供一种在您的案例中应用此方法的方法。请告诉我。

您的问题是在迭代列表时从列表中删除项目,这会更改列表的大小

最简单的方法可能是

foreach (GameObject toDestroy in destroyEnviroment.gameObjectsToDestroy)
{
    Destroy(toDestroy);
}
destroyEnviroment.gameObjectsToDestroy.Clear();
编辑:
值得注意的是,这里我
Destroy
在删除之前,这似乎违反直觉,但原因是调用Destroy将在帧结束时设置要销毁的对象,然后我们可以忘记它并清除列表-其他一切都将得到处理。

如果不需要,我极力主张不要从列表中删除项目——在这种情况下,您将清除整个列表,因此您可以使用
clear()

,但在这种情况下,您实际上不需要更改循环类型,Jay建议在循环之外清除它的内容在您的情况下就足够了。有时在某些情况下它可能不起作用。我倾向于使用的另一个选项是
while(collection.Any)
,如果您知道要清除列表中的每个项目。请记住,如果从一开始就删除元素(如
列表),某些数据类型可能是
O(n)
。谢谢。我是新的团结,这是非常推动我前进。你最好<代码>foreach(GameObject toDestroy in Destroyment Environment.gameObjectsToDestroy.ToList())
Thx。但是为什么不使用while循环(list.Count>0),在该循环中销毁并从列表中删除元素[0]?在我的情况下,它总是出现:“不在范围内”。@Thboss将更新我的答案以回应此问题
foreach (GameObject toDestroy in destroyEnviroment.gameObjectsToDestroy)
{
    Destroy(toDestroy);
}
destroyEnviroment.gameObjectsToDestroy.Clear();