【问题标题】:Sliding AABB collision - getting stuck on edges滑动 AABB 碰撞 - 卡在边缘
【发布时间】:2011-04-23 13:58:37
【问题描述】:

我正在开发一款基于 3D 瓷砖的游戏,并且正在使用 AABB 碰撞检测。对于玩家相交的每个立方体,我找到玩家与立方体相交最少的轴,然后沿着该轴将玩家推出立方体。

根据签入多维数据集的顺序,当沿多个多维数据集的边缘滑动时,这可能会导致问题。我创建了一个应该解释问题的图表:

http://imgur.com/mmK0W.png

  • 箭头#1 是玩家尝试的移动。其他箭头是碰撞响应。
  • 在左图中,首先对右侧立方体进行碰撞测试,导致玩家被推向左侧,然后向上推。 (不好
  • 在右图中,首先测试与左侧立方体的碰撞,导致玩家被向上推,此时玩家不再与另一个立方体相交。 (

对于解决此问题的最有效方法有什么想法吗?或者有什么更好的方法来处理碰撞响应?

谢谢。

【问题讨论】:

  • 也许检查所有碰撞并记录碰撞的时间(或距离)。仅应用最快发生的碰撞。可以选择在剩余的时间步长中继续该过程。
  • 因此,如果我按与玩家的距离对玩家与之相交的所有立方体进行排序,然后一次考虑一个,这可能会奏效。我认为最好避免每帧都对事物进行排序,但我不确定这会很重要,因为玩家最多只能与 ?7 发生碰撞?一次块。你觉得那里有什么好担心的吗?

标签: algorithm geometry collision game-physics


【解决方案1】:

仅在需要时(立方体/方向重叠),离散实现会迫使您在系统中注入一些连续数学。

对于每个立方体 c1c2 ... ci 与用户立方体 (uc) 相交在检查时,您想找出首先“触摸”了哪个立方体 - 只有一个,就像在现实生活中一样。考虑uc的方向d,取ciuc的数量(重叠)求出cu的位置 当时它“触动”了 ci

首先确定哪个立方体被“触摸”cj(在d 轴上需要最多回滚的那个 - 时间越早)并仅使用这个来计算碰撞反应。

不仅您会达到准确性。但如果所有立方体都在移动、速度不同等会有所帮助...

【讨论】:

  • +1。我曾经做过一次这样的事情,尽管实现和调试很痛苦。当对象从一帧到下一帧的运动不是沿着直线时,使用这种方法可能会遇到麻烦,但除此之外它工作得很好。您需要记住每个可以移动的对象的先前位置(可能还有先前的速度),以便您可以在两帧之间的任何给定时间计算对象的位置和速度。
  • 我有点难以理解你在说什么,但我认为如果玩家试图走进房间的角落,这个答案也会有问题。我认为有必要考虑不止一个区块。我或许可以对玩家碰撞的所有方块进行排序,但我不确定是否最好避免对事物进行排序。
  • 房间的墙壁与其他立方体的处理方式相同 - 这是一个特殊(更简单)的情况:您检查立方体是否超出范围,并且使用相同的算法,确定有多少多维数据集出来,然后检查与其他多维数据集的碰撞。同样,第一个“接触”(另一个立方体或墙壁)必须处理碰撞反应。墙只是立方体可能与它发生碰撞的一个特定的不移动且更大的物体。
  • 我是说如果玩家走进角落,他将与 3 个立方体相交(如果这是 2D 的话)。当玩家必须沿两个轴移动时,我将如何仅使用一个立方体计算适当的响应?我想我必须按距离对它们进行排序,并可能考虑它们中的每一个。虽然在这种情况下我只需要考虑两个。
【解决方案2】:

从您的图表中,您似乎想要最小化玩家和立方体之间重叠的最小移动。每个有重叠的立方体都会尝试在两个正交方向上“推动”玩家。你能做一些事情,比如在每个方向上选择最大推动力中的最小推动力吗?

【讨论】:

  • 我认为如果玩家走进角落会导致问题。在这种情况下,我需要将播放器沿 2 轴向后推。
  • 好的;在 2D 中思考,push 必须具有垂直和水平分量。每个重叠的立方体可以从 {N, S, E, W} 向两个方向施加推动力。如果有多个重叠的立方体,那么您需要考虑 {N, S} 和 {E, W} 方向上的最大推动(任何更少都会留下重叠,但可以忽略,例如,NS 推动,因为电子战推送将完成这项工作)。最多有八种可能性。你能按数量级尝试所有八个并选择第一个将玩家从立方体中清除的吗?
  • 不幸的是,在 3 维中会有更多可能的集合。正如 Tom 建议的那样,最初根据距离对块进行排序可能会更有效。
  • 嗯,3D 最多有 26 种可能性,而您必须考虑所有这些可能性的唯一方法是玩家立方体的每个面是否都与游戏立方体相交。
【解决方案3】:

当您连续的两个(或更多)静止立方体可以组合成一个更大的矩形时,您可能会实现一种混合宽相位。首先测试较大的矩形。它会给你绿色复选标记的结果,并且比检查每个立方体更快。然后,在此之后,仅在需要时检查各个多维数据集。

【讨论】:

  • 我正在尝试如何将其应用于 3 个维度。如果我有一个像“L”这样直立的形状,我可以水平或垂直组合 2 个块。但我认为我必须应用响应的顺序取决于玩家的位置或移动方向。
【解决方案4】:

碰撞只能在 1 个轴上推动对象。确定要推动的轴:

else   -- not this
elseif -- change to this

if w > h then
    push x
elseif h > w then
    push y
end

如果您的图块对齐,则此方法有效。

使用圆圈避免粘在未对齐的瓷砖上

【讨论】:

    猜你喜欢
    • 2018-02-20
    • 1970-01-01
    • 2011-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-26
    相关资源
    最近更新 更多