基本问题:当玩家在由多个碰撞器组成的平面上移动时,Unity 的物理引擎会产生奇怪的碰撞。鬼碰撞发生在 Colliders 之间的关节处,并表现为两种行为:
根据 Bennett Foddy 的演讲,这似乎是一般物理引擎的问题:
https://www.youtube.com/watch?v=NwPIoVW65pE&ab_channel=GDC
游戏细节:在我的例子中,玩家正在通过一个程序生成的虫洞,该虫洞由使用 MeshCollider 的 Segment 对象组成。虫洞在 3D 空间中随机扭曲,而宽度和高度则动态变化。玩家可以在隧道内部进行 360 度扫射(重力方向与位置相关)。
这使得我发现的更简单的解决方案变得不切实际。其中包括:
- 使用单个对象而不是多个对象
- 在关节后面放置多余的碰撞器
我设法在 OnCollisionEnter() 中标记了这些错误的碰撞。PlayerController 上的这个方法可以很好地识别这些错误的碰撞,并引发一个标志。
private void OnCollisionEnter(Collision other)
{
if (other.gameObject.tag != "Tunnel"){return;}
// Bit mask for tunnel layer.
int tunnelLayerMask = 1 << 10;
// Get the direction from the nearest Segment's origin to the collision point.
Vector3 toCollision = other.contacts[0].point - nearestSegment.transform.position;
if (Physics.Raycast(nearestSegment.transform.position, toCollision, out RaycastHit hit, 100f, tunnelLayerMask))
{
// Flag the collision if the detected surface normal
// isn't equal to the collision normal.
if (other.contacts[0].normal != hit.normal) { colFidelityFlag = true; }
}
}
但是在优雅地解决问题时,我完全不知所措。
目前,我只是在每帧缓存玩家的速度。如果标记了碰撞,我会用前一帧的缓存速度覆盖结果速度。这适用于大多数情况:玩家在不知不觉中进入地板一帧,并越过有问题的关节。但是在足够高的速度或与隧道内的障碍物相互作用的情况下,玩家有可能被弹出地板并进入太空。我不想过多地限制玩家的速度,因为游戏的感觉部分依赖于高速和硬碰撞。
有谁知道解决这些错误碰撞的更好方法?