概念检查器:Farseer中的碰撞情况

4

我已经使用Farseer一段时间了,参与了一个物理教学平台项目。我的大脑里有几个问题一直没有解答,其中很多是关于引擎的碰撞处理。

许多人似乎都有难以理解引擎工作的问题,部分原因是Farseer缺乏适当的API。对于那些知道的人来说,确认以下概念并消除任何错误概念可能是个好主意。

概念0:两个阶段

Farseer中的碰撞分为两个阶段:

  1. 广义碰撞检测
  2. 精确碰撞(请纠正我的术语使用,如果有更官方的名称......)

概念1:广义碰撞检测

使用广义碰撞检测,Farseer将在场景中寻找潜在的碰撞。所谓的广义碰撞检测是通过......

  1. The use a quad tree, which can be found in package "Farseer.Collision".

  2. The class "Farseer.Dynamics.World" has a reference to "Farseer.Collision.QuadTreeBroadphase".

  3. "Farseer.Collision.QuadTreeBroadphase" has a reference to "Farseer.Collision.QuadTree".

  4. Further bounding box test is also done.

  5. If we ever find a need to know which pair(s) of fixtures has the potential to collide, we may do this...

    /* Game.Initialize */
    public override void Initialize() {
        OtherIrrelevantInitCode();
        _world.OnBroadphaseCollision += BroadphaseHandler;
        base.Initialize();
    }
    public void BroadphaseHandler(ref FixtureProxy fp1, ref FixtureProxy fp2) {
        // code to read about fp1 and fp2
    }
    

但是...

小问题1

有哪些情况是有用的,让我们知道哪些夹具对可能发生碰撞?

概念2:事件的含义

两个关键词的定义:

  1. 接触:两个物体接触。数组Manifold.Points不为空
  2. 碰撞:两个物体第一次接触。

BeforeCollision意味着两个物体没有碰撞,也没有接触

OnCollision意味着两个物体正在碰撞,但不会触发接触

AfterCollision意味着两个物体曾经碰撞,但现在只接触

OnSeparation意味着两个物体曾经接触,但现在没有。

概念3:使用事件

宽相碰撞测试和精确碰撞测试总是要进行。

可以通过在事件OnCollision中返回false或使用IgnoreCollision方法来禁用精确碰撞。

我听过不止一次人们说“只需将OnCollision留空并返回true”。这到底是什么意思?使用事件意味着我们希望在发生上述事件时应用其他效果(例如杀死敌人、得分、播放声音等)。

1个回答

3

本答案适用于Farseer Physics 3.3.1版本(写作时的当前稳定版本)。


Broad-phase只是一种性能优化。它快速确定可能发生碰撞的物体,以便那些不可能发生碰撞的物体不需要运行更昂贵的窄相碰撞检测。


根据我的经验,Farseer中的事件设计并不像它们本应该做得那样好。我发现我必须修改它们以适应我的游戏——但幸运的是,这段代码实际上并不难阅读和修改。此外,文档在某些地方并不准确。

以下是Farseer Physics中事件的实际作用:

BeforeCollision发生在广相注册新的潜在碰撞之前,在它为两个固定装置创建Contact对象之前。您可以通过在事件处理程序中返回false来阻止Contact的创建。

Contact的存在并不一定意味着这两个固定装置实际上处于接触状态——只是广相成功了。一个Contact可以接触/不接触,并且可以启用/禁用(它们开始时是启用的并且未接触)。

OnCollision发生在Contact从未接触到接触时。您可以通过返回false来禁用该联系。奇怪的是,如果您返回true,则可以重新启用另一个事件处理程序在该步骤中禁用的联系(这是我为自己的游戏所更改的内容之一)。

仅启用、接触的接触对物理模拟产生任何影响。

OnSeparationOnCollision的相反:当接触从接触到非接触时触发。这里没有禁用/启用联系的方法。

AfterCollision针对每个在该帧上涉及物理模拟的Contact(因此:启用、接触和未在休眠岛中的那些)。它在物理模拟步骤之后调用,但在清理之前——尤其是在清除Body.ForceBody.Torque之前(适用于声音效果等)。


通常,您只需使用这些事件来触发您的效果——粒子、声音、游戏机制(如销毁对象)等。在这种情况下,您订阅任何一个您想要的事件,执行任何您喜欢的操作,然后返回true(不要禁用/覆盖联系)。

如果您想要修改物理引擎或者禁用联系,那么情况将变得更加复杂(尤其是当您意外地通过另一个事件处理程序重新启用它们时,如我之前所提到的)。如果Farseer的内置事件不能满足您的需求,那么自己添加代码也是完全合理的。在这个高级阶段,从源代码构建实际上是必要的,以便您可以准确地检查正在发生的事情。


忘记注明我所说的引擎版本了:P 是3.3.1版本。 - Felastine
需要注意的是,在v3.5中,引擎添加了一个选项,可以按照您所描述的方式进行操作,并且仅在所有OnCollision回调函数返回true时才启用联系人。 - dazerdude

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接