联系人和类别位掩码 - 是否只需要设置一个,或者两者都需要设置?

Contact and category bitmask - does only one, or both, need to be set?

所以我正在学习如何检查 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 步:现在我们决定哪些对象相互碰撞。


比如球对象,有与球场、地棒和边界的碰撞。设置如下,按位或运算,假设 ballBodySCNPhysicsBody:

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

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


在这里,您设置了 contactTestBitMask。例如,对于球,我想在它与球场、地面、球棒、边界接触时得到通知。同样,要做到这一点:

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

当您设置 contactTestBitMask 时,您将在物理委托中处理联系人通知,这将是这样的:

- (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;联系人掩码实际上应该是对象的类别掩码的按位或运算,将有联系人并且您希望收到通知。

我觉得文档有点混乱,希望上面的解释能解开你的疑惑。