问题 无法理解碰撞位掩码的工作原理


我试图在Swift中使用碰撞位掩码和接触测试位掩码,我希望两个对象不要碰撞在一起,所以我在做:

firstNode.physicsBody?.collisionBitMask = 0b01
secondNode?.collisionBitMask = 0b10

由于SpriteKit对这两个数字进行AND运算,因此结果不应该如此 00 以来 10 & 01 = 00 ?

那么为什么碰撞会发生呢?

谢谢。


6929
2017-08-21 12:02


起源



答案:


这不是碰撞处理的工作原理。当两个物体交叉时,物理引擎执行逻辑 AND 当前身体之间的操作员 collisionBitMask 和其他人的身体 categoryBitMask

当两个物理实体相互接触时,可能会发生碰撞。   该身体的碰撞面具与其他身体的类别进行比较   通过执行逻辑AND操作进行掩码。如果结果是非零   值,这个身体受到碰撞的影响。每个身体独立   选择是否想要受到其他身体的影响。对于   例如,您可以使用它来避免碰撞计算   对身体的速度做出微不足道的改变。

资源

所以结果取决于你如何设置 categoryBitMask 在这两个机构上。默认值 categoryBitMask 是 0xFFFFFFFF,表示所有位设置。所以当你表演和之间 0xFFFFFFFF 和 0b10 要么 0b01,结果将是非零值,因此是碰撞。

例如,像这样设置你的身体:

spriteA.physicsBody?.categoryBitMask = 0b01
spriteA.physicsBody?.collisionBitMask = 0b01

spriteB.physicsBody?.categoryBitMask = 0b10
spriteB.physicsBody?.collisionBitMask = 0b10

会给你想要的结果。此外,这可能不是您需要的确切设置,它只是一个简单的示例,您必须根据需要更改值。在这种情况下,spriteA只会与具有的物体碰撞 categoryBitMask 设置 0b01。同样适用于spriteB,它会与具有的物体碰撞 categoryBitMask 设置 0b10

此外,如果您不希望这些精灵能够与任何东西发生碰撞,只需设置它们即可 collisionBitMask 属性为0。


7
2017-08-21 13:26



哇谢谢你这个详细的答案!解决了我的问题! - Trevör Anne Denise


答案:


这不是碰撞处理的工作原理。当两个物体交叉时,物理引擎执行逻辑 AND 当前身体之间的操作员 collisionBitMask 和其他人的身体 categoryBitMask

当两个物理实体相互接触时,可能会发生碰撞。   该身体的碰撞面具与其他身体的类别进行比较   通过执行逻辑AND操作进行掩码。如果结果是非零   值,这个身体受到碰撞的影响。每个身体独立   选择是否想要受到其他身体的影响。对于   例如,您可以使用它来避免碰撞计算   对身体的速度做出微不足道的改变。

资源

所以结果取决于你如何设置 categoryBitMask 在这两个机构上。默认值 categoryBitMask 是 0xFFFFFFFF,表示所有位设置。所以当你表演和之间 0xFFFFFFFF 和 0b10 要么 0b01,结果将是非零值,因此是碰撞。

例如,像这样设置你的身体:

spriteA.physicsBody?.categoryBitMask = 0b01
spriteA.physicsBody?.collisionBitMask = 0b01

spriteB.physicsBody?.categoryBitMask = 0b10
spriteB.physicsBody?.collisionBitMask = 0b10

会给你想要的结果。此外,这可能不是您需要的确切设置,它只是一个简单的示例,您必须根据需要更改值。在这种情况下,spriteA只会与具有的物体碰撞 categoryBitMask 设置 0b01。同样适用于spriteB,它会与具有的物体碰撞 categoryBitMask 设置 0b10

此外,如果您不希望这些精灵能够与任何东西发生碰撞,只需设置它们即可 collisionBitMask 属性为0。


7
2017-08-21 13:26



哇谢谢你这个详细的答案!解决了我的问题! - Trevör Anne Denise


这不是测试具有冲突位的节点之间的交互的方式。

  • categoryBitMask是对象的类别。
  • collisionBitMask是碰撞时对象响应的内容。
  • contactTestBitMask用于指定位掩码发生交叉时的通知。

假设我有以下内容:

struct PC {
    static var player: UInt32 = 0b10 //2
    static var enemy: UInt32 = 0b100 //4
    static var rock: UInt32 = 0b1000 //8
}

player.physicsBody!.categoryBitMask = PC.player
player.physicsBody!.collisionBitMask = PC.enemy | PC.rock
enemy.physicsBody!.categoryBitMask = PC.enemy
enemy.physicsBody!.collisionBitMask = PC.player

因此,当您检查didBeginContact函数中何时发生交互时,您可以使用位逻辑检查它们是否发生了交互。

func didBeginContact(contact: SKPhysicsCountact) {
    //1
    let collision: UInt32 = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask

    //2
    if collision == PC.player | PC.enemy {
        //An interaction occured between the player and enemy.
    }
  1. 变量碰撞使用按位OR,即|。在这种情况下(如果玩家接触敌人),它获得玩家(bodyA)的类别为2,它获得敌人的类别(bodyB),即4.所以2(0b10)或4( 0b100)等于6(0b110),它被分配给碰撞。

  2. 那么在if语句中,它检查6的碰撞是否等于(PC.player | PC.enemy),这是真的,因此在玩家和敌人之间发生了交互,因为它将是6 == 6。

您可以使用变量碰撞来测试任何交互。例如,在我的测试游戏中,我有以下功能来测试触摸的对象。

func didBeginContact(contact: SKPhysicsContact) {
    let collision: UInt32 = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask

    //Collision between the penguin and land
    if collision == PhysicsCategory.Land | PhysicsCategory.Animal {
        lostLevel()
    } else if collision == PhysicsCategory.Animal | PhysicsCategory.Pillow {
        animalCounter -= 1
        if animalCounter == 0 {
            wonLevel()
        }
    }
}

3
2017-08-22 08:23



非常感谢你的回答!! - Trevör Anne Denise
这是一个详细的解释。因此,冲突位掩码用于识别系统的冲突,并触发didBeginContant函数,其中categoryBitMask可用于隔离发生的冲突。 - nnrales