我一直在研究基于碰撞和滑动算法的碰撞响应系统。
只是,我收到了一个错误。
这是有错误的代码:
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.List1+Enumerator[T].MoveNext ()(位于 <75633565436c42f0a6426b33f0132ade>:0)1+Enumerator[T].MoveNextRare () (at <75633565436c42f0a6426b33f0132ade>:0) System.Collections.Generic.List
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
循环)时,它似乎可以工作。
这里有一个非常相似的问题。如果我没记错的话,如果集合像您已经展示的那样发生更改,foreach
会感到困惑。您可以在代码中尝试使用
ToList()
作为
foreach(CollisionRepsonse CollisionRepsonse in CollisionHits.toList())
。我没有尝试过,但可能会解决您的问题。我想你也可以使用
for
循环。 For 循环不介意在循环中间改变东西。