4

我使用 Farseer 已经有一段时间了,正在做一个物理教学平台项目。我脑子里有几个关于引擎的问题在很长一段时间内都没有得到解答,其中许多是关于引擎的碰撞处理。

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

概念 0:两个阶段

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

  1. 宽相碰撞
  2. 精确碰撞(请更正我对术语的使用,如果有另一个更正式的名称......)

概念 1:Broadphase

Farseer 使用广泛的相位碰撞,将在场景中发现潜在的碰撞。所述宽相碰撞测试由...

  1. 使用四叉树,可以在包“Farseer.Collision”中找到。

  2. “Farseer.Dynamics.World”类引用了“Farseer.Collision.QuadTreeBroadphase”。

  3. “Farseer.Collision.QuadTreeBroadphase”引用了“Farseer.Collision.QuadTree”。

  4. 还进行了进一步的边界框测试。

  5. 如果我们发现需要知道哪对固定装置有可能发生碰撞,我们可以这样做......

    /* 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

有哪些常见情况有助于我们了解哪些设备对可能发生碰撞?

概念二:事件的意义

定义两个关键字:

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

BeforeCollision表示两个对象没有碰撞没有接触

OnCollision表示两个对象正在碰撞,但触摸不会触发此事件。

AfterCollision意味着两个物体正在碰撞,但现在它们只是接触

OnSeparation表示两个对象正在接触,但现在它们不是。

概念 3:使用事件

宽相碰撞测试和精确碰撞测试始终进行。

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

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

4

1 回答 1

3

此答案适用于 Farseer Physics 3.3.1(当前稳定版本,在撰写本文时)


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


以我的经验,Farseer 中的事件没有设计得尽可能好。我发现我不得不为自己的游戏修改它们——但幸运的是,这段代码实际上并不难阅读和修改。此外,文档在某些地方也不准确。

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

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

a 的存在Contact并不一定意味着这两个夹具实际上是接触的——只是广泛阶段成功了。AContact可以触摸/不触摸,并且可以启用/禁用(它们开始时启用和不触摸)。

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

只有启用的触摸接触对物理模拟有任何影响。

OnSeparation是相反的OnCollision:当接触从接触变为不接触时触发。无法在此处禁用/启用联系人。

AfterCollision在该帧上的物理模拟中涉及的每一个都被调用Contact(所以:那些被启用、触摸而不是在一个睡着的岛上)。它在物理模拟步骤之后调用,但在清理之前 - 最值得注意的是之前Body.ForceBody.Torque被清理(对于声音效果等很方便)。


通常你只是使用这些事件来触发你的效果——粒子、声音、游戏机制,比如摧毁物体,等等。在这种情况下,您订阅您想要的任何一个,做任何您喜欢的事情,然后返回 true (不禁用/覆盖联系人)。

如果您想弄乱物理引擎或禁用联系人(尤其是当您意外地使用另一个事件处理程序重新启用它们时,正如我之前提到的),它会变得更加复杂。如果 Farseer 的内置事件对您不起作用,那么进入它的代码并添加您自己的代码是完全合理的。在这个高级级别,实际上有必要从源代码构建,这样您就可以准确地检查到底发生了什么。

于 2012-11-16T11:17:38.663 回答