swift - 联系人和类别位掩码 - 只需要设置其中之一还是两者都需要设置?

标签 swift scenekit

所以我正在学习如何在 Swift 中检查位掩码冲突,并且我对是否将两个实体设置为具有彼此的接触位掩码感到困惑。

我的困惑来自文档中的以下内容:

When two physics bodies overlap, a contact may occur. SceneKit compares the body’s contact mask to the other body’s category mask by performing a bitwise AND operation. If the result is a nonzero value, SceneKit creates an SCNPhysicsContact object describing the contact and sends messages to the contactDelegate object of the scene’s physics world.

据我了解,碰撞不需要是相互的 - 换句话说,一个可以与另一个碰撞,而另一个则保持不动。如果我错了,请纠正我。但在接触测试时,如果A的类别掩码设置为1,接触位掩码设置为2,并且B 的类别掩码设置为 2,其联系人位掩码设置为 4,然后将 AB 冲突注册为联系人?如果 B 现在将其联系人位掩码设置为 1 会怎样?会记录两次碰撞吗?

最佳答案

让我尝试用实际游戏代码的示例来解释所有这些位掩码。该游戏具有以下对象:球、球场、地面、球棒、边界、击球树桩、保龄球树桩,它们将具有物理相互作用。

抱歉,代码是用 ObjC 编写的,但转换为 Swift 很简单。

第 1 步:设置类别位掩码,指定每个对象的类型


typedef NS_OPTIONS(NSUInteger, CollisionCategory) {
  CollisionCategoryBall = 1 << 1,
  CollisionCategoryPitch = 1 << 2,
  CollisionCategoryGround = 1 << 3,
  CollisionCategoryBat = 1 << 4,
  CollisionCategoryBoundary = 1 << 5,
  CollisionCategoryBattingStumps = 1 << 6,
  CollisionCategoryBowlingStumps = 1 << 7,
};

第 2 步:现在我们决定哪些对象彼此发生碰撞。


例如,对于球对象,存在与球场、地面球棒和边界的碰撞。设置如下,按位 OR 运算,假设 ballBodySCNPhysicsBody:

ballBody.collisionBitMask =
      (CollisionCategoryPitch | CollisionCategoryGround | CollisionCategoryBat |
       CollisionCategoryBoundary);

第 3 步:(可选),如果您希望在两个物理体相互接触时收到通知。


在这里,您设置 contactTestBitMask。以球为例,我希望在它与球场、地面、球棒、边界接触时收到通知。再次强调,要做到这一点:

ballBody.contactTestBitMask =
      (CollisionCategoryPitch | CollisionCategoryGround | CollisionCategoryBat |
       CollisionCategoryBoundary);

当您设置contactTestBitMask时,您将在物理委托(delegate)中处理接触通知,如下所示:

- (void)physicsWorld:(SCNPhysicsWorld*)world
     didBeginContact:(SCNPhysicsContact*)contact {
  CollisionCategory contactMask = contact.nodeA.physicsBody.categoryBitMask |
                                  contact.nodeB.physicsBody.categoryBitMask;
  if ((contactMask == (CollisionCategoryBall | CollisionCategoryPitch)) &&
      !self.ballLandedOnPitch) {
    NSLog(@" Ball hit the pitch");
  }
  ...
}

因此,总的来说,您只需对对象进行分类,然后设置碰撞掩码,这只是将发生碰撞的对象的类别掩码的按位或运算,并且可以选择处理物体之间的接触,设置接触测试位掩码。

But when it comes to contact testing, if A has its category mask set to 1 and contact bitmask set to 2,

我不确定您是否打算将联系人位掩码显式设置为上面的 2;联系人掩码实际上应该是对象的类别掩码的按位或运算,与该对象有联系人并且您希望收到通知。

我认为这些文档有点令人困惑,希望上述解释能消除您的疑虑。

关于swift - 联系人和类别位掩码 - 只需要设置其中之一还是两者都需要设置?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41341729/

相关文章:

swift - 单击 CallKit 中的应用程序图标时打开应用程序

ios - 如何向 uiviewcontroller 添加圆角半径

scenekit - 如何更新 SceneKit 游戏中的 GameplayKit 实体和组件

macos - SceneKit CFURLCreateDataAndPropertiesFromResource 失败,错误代码为 -11

ios - 将 ViewController 与 GuestureRecognizers 相乘

ios - Firebase:从未知子级检索嵌套数据

swift - 在 Swift 中捕获异常?

ios - 使用 SceneKit 在 ARKit 中拖动 SCNNode

ios - SceneKit中convertPosition的解释

swift - 如何访问 ARSCNDebugOptions.showBoundingBoxes?