我的碰撞响应出了什么问题?

问题描述 投票:0回答:1

我一直在研究基于碰撞和滑动算法的碰撞响应系统。

只是,我收到了一个错误。

这是有错误的代码:

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

[System.Serializable]
public class CollisionRepsonse
{ 
    public float RemainingVelocity;
    public RaycastHit CollisonHit;
    public Vector3 CollisionHitLocation;
    public Vector3 OutputForce;
}

public class NewBehaviourScript : MonoBehaviour
{
    public Vector3 CurrentInputDir;
    public float BaseVelocity = 5f;

    [SerializeField] List<CollisionRepsonse> CollisionHits;

    RaycastHit InitialCollisonHit;
    bool FirstCollisionHit;

    public int i = 0;

    void Update()
    { 
        if(Physics.CapsuleCast(transform.position, transform.position, 0.5f, CurrentInputDir, out InitialCollisonHit, BaseVelocity))
        { 
            if (CollisionHits.Count == 0f)
            { 
                FirstCollisionHit = true;
            }

            if (FirstCollisionHit)
            { 
                CollisionHits.Add(new CollisionRepsonse{}); 
                FirstCollisionHit = false;
            }

            if (CollisionHits.Count != 0f) 
            {
                CollisionResponseFunction();    
            }

            void CollisionResponseFunction()
            { 
                foreach(CollisionRepsonse CollisionRepsonse in CollisionHits)
                {
                    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);                         
                    }
                    else
                    { 
                        //CollisionHits[i].CollisionHitLocation = CollisionHits[i - 1].CollisonHit.point;
                        //CollisionHits[i].RemainingVelocity = CollisionHits[i - 1].RemainingVelocity - Vector3.Distance(CollisionHits[i - 1].CollisionHitLocation, CollisionHits[i].CollisionHitLocation);
                        //CollisionHits[i].OutputForce = Vector3.ProjectOnPlane(CollisionHits[i - 1].OutputForce, CollisionHits[i - 1].CollisonHit.normal);  
                    }

                    if (CollisionHits[i].RemainingVelocity > 0f) 
                    { 
                        CollisionHits.Add(new CollisionRepsonse{});    
                        i++;
                    }
                }                
            }
        }
    }
}

我收到的错误是:

InvalidOperationException:集合被修改;枚举操作可能无法执行。
System.Collections.Generic.List

1+Enumerator[T].MoveNextRare () (at <75633565436c42f0a6426b33f0132ade>:0)   System.Collections.Generic.List
1+Enumerator[T].MoveNext ()(位于 <75633565436c42f0a6426b33f0132ade>:0)
NewBehaviourScript.g__CollisionResponseFunction|6_0 ()(位于 Assets/Scripts/NewBehaviourScript.cs:46) NewBehaviourScript.Update ()(位于 Assets/Scripts/NewBehaviourScript.cs:41)

但是一旦我将代码更改为:

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

[System.Serializable]
public class CollisionRepsonse
{ 
    public float RemainingVelocity;
    public RaycastHit CollisonHit;
    public Vector3 CollisionHitLocation;
    public Vector3 OutputForce;
}

public class NewBehaviourScript : MonoBehaviour
{
    public Vector3 CurrentInputDir;
    public float BaseVelocity = 5f;

    [SerializeField] 
    List<CollisionRepsonse> CollisionHits;

    RaycastHit InitialCollisonHit;
    bool FirstCollisionHit;

    public int i = 0;

    void Update()
    { 
        if (Physics.CapsuleCast(transform.position, transform.position, 0.5f, CurrentInputDir, out InitialCollisonHit, BaseVelocity))
        { 
            if (CollisionHits.Count == 0f)
            { 
                FirstCollisionHit = true;
            }

            if (FirstCollisionHit)
            { 
                CollisionHits.Add(new CollisionRepsonse{}); 
                FirstCollisionHit = false;
            }

            if (CollisionHits.Count != 0f) 
            {
                CollisionResponseFunction();    
            }

            void CollisionResponseFunction()
            { 
                foreach(CollisionRepsonse CollisionRepsonse in CollisionHits)
                {
                    if (CollisionHits[i].RemainingVelocity > 0f) 
                    { 
                        CollisionHits.Add(new CollisionRepsonse{});    
                        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);                         
}

它在

foreach
循环上抛出错误,表示集合已修改。我确信类中的值已被修改,但这就是重点,我会在其中存储数据,但它与 foreach 循环中的计数器无关 - 只是与其中的值有关。

我确保同时增加整数和列表计数以避免这个问题,并且我确保向后计算而不是向前计算。

我尝试了所有方法,但找不到问题所在。我希望它能正常工作,因为我在计算中找不到任何错误......

但是当我删除上面提到的代码部分(这不应该干扰

foreach
循环)时,它似乎可以工作。

c# unity-game-engine unityscript
1个回答
0
投票

这里有一个非常相似的问题。如果我没记错的话,如果集合像您已经展示的那样发生更改,foreach

会感到困惑。您可以在代码中尝试使用 
ToList()
 作为 
foreach(CollisionRepsonse CollisionRepsonse in CollisionHits.toList())
。我没有尝试过,但可能会解决您的问题。

我想你也可以使用

for

 循环。 For 循环不介意在循环中间改变东西。

© www.soinside.com 2019 - 2024. All rights reserved.