【问题标题】:How to fix Unity collision problem with 2D sprites如何使用 2D 精灵修复 Unity 碰撞问题
【发布时间】:2019-09-14 03:30:07
【问题描述】:

所以我在这里制作了这个游戏:https://youtu.be/OxJEeOTldcM

我遇到了迷宫墙的碰撞器的问题,在某些关卡(不仅仅是我在下面的视频中展示的那个),当球被墙撞到墙上时,它会穿过墙壁移动。 在这里你可以看到我在说什么:https://youtu.be/dVU3LWKuXJ0

我已经解决了这个问题,并通过使迷宫的旋转速度比我最初打算的慢很多来妥协。我希望迷宫的旋转速度与玩家的移动速度一样快,但这会让球穿过每一面墙。

所以我创建这些关卡的方式是这样的:我有这些预制的 PNG 迷宫,我将它们导入关卡并在它们上应用 Polygon Collider 2D。但似乎单独的 Polygon Collider 无法正确处理我的游戏的碰撞。

不仅如此,我还开始在其中一些墙上用盒子碰撞器将一些空的游戏对象分层,试图让它们更强大。这确实有效,但还不够,球会不断穿过其中的一些。

球和墙壁上都有刚体,根据我在网上看到的一些关于不良碰撞检测的答案,我将它们的碰撞检测设置为连续。还是没修好。

我也尝试过在 Photoshop 中让那些迷宫的墙壁变厚,但如果不破坏球应该移动的空间,以及扭曲迷宫的外观,我不能比现在更厚。

必须有一种方法可以解决 Unity 的这种不良冲突。我需要球停止穿墙,因为这显然是我比赛的重要组成部分。 我还希望能够将迷宫的旋转设置为与玩家的移动一样快,而不必限制其速度,但老实说,如果我能以当前速度解决这个碰撞问题,我会很高兴。

【问题讨论】:

  • 你能告诉我们你的球和迷宫检查员吗?你能告诉我们你是如何旋转迷宫和移动球的吗?
  • @AresCaelum 当然。这是我的迷宫检查器:imgur.com/zGOhDAW 这是球的检查器:imgur.com/XuLLxqn 这是我用来旋转迷宫的脚本:imgur.com/nhbg9Ti 球的运动只是来自刚体的重力。
  • 您是否尝试过使用内置物理系统来旋转您的对象?目前,您有 2 个刚体,并且您在正常更新而不是固定更新中手动调整旋转,这会导致您的物理交互问题并使球穿过墙壁
  • @AresCaelum 只需将更新功能设置为 FixedUpdated 即可解决此问题。非常感谢您指出!我还能够加快迷宫的旋转。我尝试将您的答案标记为正确,但我认为它必须作为答案而不是评论发布。
  • 是的,它必须是一个答案,我没有写答案是因为我试图解决这个问题,但是 Erik Overflow 有一篇关于物理相互作用的很好的文章,以及更新之间的差异和 FixedUpdate。

标签: unity3d


【解决方案1】:

“穿墙”最常见的原因不是严重的碰撞。这通常是由于对 Unity 对物理和帧的分离理解不足。

Unity 在固定更新周期计算碰撞和物理,并根据 CPU 资源在动态更新周期生成帧。这些通常被 Monobehaviours 中的 FixedUpdate() 和 Update() 明确利用。

Unity 中的一切都发生在这两个周期之一。基于帧的逻辑(例如对变换的更改)发生在动态更新周期中,而物理逻辑(例如碰撞)发生在固定的更新周期中。

您可能正在使用变换旋转拼图。这种对变换的旋转发生在任何物理计算之外,如果你旋转得足够快,你最终可能会在物理计算有机会运行并产生碰撞之前剪穿墙壁。当您具有非常高的 FPS(例如检查员的无上限 FPS)时,这一点非常明显。但是,锁定您的 FPS 只会掩盖问题,并且该错误仍然可能发生。

为了解决您的问题,我恳请您改为对 Rigidbody2D 本身进行旋转更改。像这样的东西应该可以工作:

public class SimpleRotation: MonoBehaviour
{
    Rigidbody2D rigidBody2D;

    void Start()
    {
        rigidBody2D = GetComponent<Rigidbody2D>();
    }

    void FixedUpdate()
    {
        if(rotateRight)
            rigidBody2D.rotation += 1.0f;
        if(rotateLeft)
            rigidBody2D.rotation -= 1.0f;
    }
}

还有一点需要注意的是,Unity 只更新帧上的输入,所以如果您在 FixedUpdate() 期间读取您的输入,您可能会重复读取您的输入(或完全错过它)。最好在 Update() 循环中读取您的输入,并设置一个变量以在方法之间传输逻辑。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-25
    相关资源
    最近更新 更多