【问题标题】:2D Colliders are Inconsistent in Unity2D 碰撞器在 Unity 中不一致
【发布时间】:2020-12-16 21:34:12
【问题描述】:

我正在使用 C# 在 Unity 中制作游戏,现在我正在开发一个可以向玩家发射弹丸的炮塔。它们工作正常,总是朝向玩家,但有时它们不会与玩家发生碰撞。它们直接穿过它们并进入地面,它们确实与之相撞。玩家和射弹的 Rigidbody2D 都设置为连续,所以我不知道发生了什么。经过一些基本测试后,下图显示了我发现的有关此碰撞错误的信息。抱歉,这只是一个快速的模型。

紫色点是炮塔本身和发射弹丸的地方,绿色是玩家几乎总是安全的地方,黄色是玩家有时安全的地方(看起来非常不一致,所以这只是一个近似值),红色是弹丸几乎总是与玩家发生碰撞的地方。我希望玩家始终与弹丸发生碰撞,无论它们在哪里。

我会添加我的代码,但它非常基本。正如我之前所说,我正在使用 C#,我只是使用 OnTriggerEnter2D 来查找冲突。玩家使用一个没有启用“is trigger”的盒子对撞机,而射弹使用一个盒子对撞机。对不起,如果这个问题真的很奇怪。如果您需要更多信息,请随时询问。

炮弹在炮塔处被实例化,它们的速度通过

Vector2 dir = playerRB.position - projectileRB.position;
    angle = Mathf.Atan2(dir.y, dir.x);
    xVel = projectileSpeed * Mathf.Cos(angle);
    yVel = projectileSpeed * Mathf.Sin(angle);
    projectileRB.velocity = new Vector2(xVel, yVel);

【问题讨论】:

  • 请添加您的代码,特别是用于发射和移动弹丸以及玩家和子弹预制件的检查器设置
  • 好的,如果有帮助,我添加了一些代码

标签: unity3d collision


【解决方案1】:

如果物体移动得太快,碰撞器将无法检测到撞击。

您说您使用OnTriggerEnter2D 来触发碰撞,该碰撞调用此函数,弹丸的碰撞器和玩家必须在其中一个 FixedUpdate 调用中重叠。

如果射弹移动得太快,那么它将穿过玩家而不会重叠,因为在 1 '帧'它在玩家身后,而在下一帧它通过它。 这就是导致不一致的原因。

理论上你可以通过增加每秒的物理计算来解决它,但这不适合你的情况。

因为射弹移动速度快并且直线移动,你应该用raycast检查玩家是否在射弹前面,并使用它来检查射弹是否击中玩家,如果射线碰撞与玩家一起,记录一次命中,确保你没有太长的光线,因为这会给你带来误报,但还要确保即使玩家的帧率很低,那么检测仍然是 100 % 一致

如果你想让游戏更公平,那么你可以在射弹后面添加另一个射线投射,并且只有当两条射线都检测到玩家的对撞机命中时才会触发命中。

射线的方向应该与弹丸面对的方向相同,后方的射线应该是相反的方向。

要获得方向,您可以使用 TransformDirection 来确定光线投射的方向,假设射弹正朝着它前进的方向。

我需要假设并且无法提供代码,因为您没有提供任何代码,因此我无法确定您使用什么来移动弹丸以及它的行为方式

【讨论】:

  • 我只是用 projectileRB.velocity = new Vector2 设置了弹丸的速度(我在问题中添加了我的代码)。我试过像你说的那样向前和向后投射光线,但它似乎不起作用,可能是因为播放器很小并且投射频率不够高。例如,前向射线投射和后向射线投射在穿过厚墙而不是薄地板时是相同的。代码在每次更新时制作两个新的光线投射,检查它们是否命中任何东西,然后检查它们的 transform.name 是否是播放器。
  • Afaik 这并不完全正确。如果使用 Rigidbody Unity 还计算中间步骤,并且如果对象在两次物理更新之间通过对撞机,碰撞也应该被触发
  • 我的代码是 RaycastHit2D hitInfoForward = Physics2D.Raycast(projectileRB.position, new Vector2(Mathf.Cos(angle), Mathf.Sin(angle))); RaycastHit2D hitInfoBackward = Physics2D.Raycast(projectileRB.position, new Vector2(Mathf.Cos(angle2), Mathf.Sin(angle2))); if (hitInfoForward && hitInfoBackward) { Debug.Log("两个 hitInfos 都存在,正在检查玩家"); if (hitInfoForward.transform.name == "player" && hitInfoBackward.transform.name == "player") { player.GameOver(); } } 我做错了吗?
猜你喜欢
  • 2020-12-31
  • 1970-01-01
  • 1970-01-01
  • 2018-02-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多