You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

我的碰撞响应系统报错?Collection was modified异常排查

Unity碰撞滑动算法中修改集合元素属性触发InvalidOperationException异常

我在开发Unity碰撞响应系统时,基于碰撞滑动算法实现,但遇到了一个奇怪的异常。当添加这段代码时:

if (i == 0)
{ 
    CollisionHits[i].CollisionHitLocation = InitialCollisonHit.point;
    CollisionHits[i].RemainingVelocity = BaseVelocity - Vector3.Distance(transform.position, CollisionHits[i].CollisionHitLocation);
    CollisionHits[i].OutputForce = Vector3.ProjectOnPlane(CurrentInputDir, InitialCollisonHit.normal);                         
}

程序触发InvalidOperationException,提示**"Collection was modified; enumeration operation may not execute"**。移除这段代码后程序正常运行。我只是修改集合内元素的属性值,并没有直接添加、删除元素或修改集合结构,完全搞不懂为什么会触发枚举异常,已经调整过逻辑但没解决。


可能原因

  • 枚举过程中隐性触发集合变更:你大概率是在foreach循环遍历CollisionHits的同时执行了这段修改代码。普通List<T>允许枚举时修改元素属性,但如果CollisionHits是Unity特殊集合(比如带变更通知的ObservableCollection<T>、序列化相关集合),修改元素属性可能会触发集合的结构变更检测,导致枚举器报错。
  • 属性setter间接修改集合:检查CollisionHit类的三个属性(CollisionHitLocation、RemainingVelocity、OutputForce)的setter方法,是否在内部偷偷修改了CollisionHits集合的结构(比如添加/删除元素、排序)。这种情况下,改属性等于间接改集合,自然触发异常。

解决方法

  1. 改用索引遍历代替foreach:如果是在foreach循环里执行修改,换成for循环直接通过索引操作,避开枚举器的检测:
    for (int i = 0; i < CollisionHits.Count; i++)
    {
        if (i == 0)
        {
            CollisionHits[i].CollisionHitLocation = InitialCollisonHit.point;
            CollisionHits[i].RemainingVelocity = BaseVelocity - Vector3.Distance(transform.position, CollisionHits[i].CollisionHitLocation);
            CollisionHits[i].OutputForce = Vector3.ProjectOnPlane(CurrentInputDir, InitialCollisonHit.normal);
        }
    }
    
  2. 检查属性setter逻辑:打开CollisionHit的类定义,确认三个属性的setter没有间接操作CollisionHits集合的代码,比如是否在setter里触发了修改集合的事件。
  3. 替换为普通List集合:如果CollisionHits是Unity特殊集合类型,尝试换成List<CollisionHit>,看看异常是否消失。

内容的提问来源于stack exchange,提问作者Niek Kleiboer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 23:52:42