collisionBitMask是如何工作的?Swift/SpriteKit

collisionBitMask是如何工作的?Swift/SpriteKit,swift,sprite-kit,skphysicsbody,Swift,Sprite Kit,Skphysicsbody,据我所知,物理实体的默认设置是当它们相互碰撞时相互反弹,直到将它们的碰撞位掩码设置为相等的数字 然而,我遇到了一个巨大的问题,因为我相信冲突,所以我要完成看起来应该非常简单的事情 let RedBallCategory : UInt32 = 0x1 << 1 let GreenBallCategory: UInt32 = 0x1 << 2 let RedBarCategory : UInt32 = 0x1 << 3 let GreenBarCategory

据我所知,物理实体的默认设置是当它们相互碰撞时相互反弹,直到将它们的碰撞位掩码设置为相等的数字

然而,我遇到了一个巨大的问题,因为我相信冲突,所以我要完成看起来应该非常简单的事情

let RedBallCategory  : UInt32 = 0x1 << 1
let GreenBallCategory: UInt32 = 0x1 << 2
let RedBarCategory : UInt32 = 0x1 << 3
let GreenBarCategory : UInt32 = 0x1 << 4
let WallCategory : UInt32 = 0x1 << 5


greenBall.physicsBody?.categoryBitMask = GreenBallCategory
greenBall.physicsBody?.contactTestBitMask = RedBarCategory
greenBall.physicsBody?.collisionBitMask = GreenHealthCategory

redBall.physicsBody?.categoryBitMask = RedBallCategory
redBall.physicsBody?.contactTestBitMask = GreenBarCategory
redBall.physicsBody?.collisionBitMask = RedHealthCategory

let borderBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
self.physicsBody = borderBody
self.physicsBody?.friction = 0
borderBody.contactTestBitMask = RedBallCategory | GreenBallCategory
borderBody.categoryBitMask = WallCategory

让RedBallCategory:UInt32=0x1您无法获得所需的行为,因为您没有正确设置类别、接触和冲突位掩码。下面是一个如何将其设置为工作的示例:

greenBall.physicsBody?.categoryBitMask = GreenBallCategory //Category is GreenBall
greenBall.physicsBody?.contactTestBitMask = RedBarCategory | WallCategory //Contact will be detected when GreenBall make a contact with RedBar or a Wall (assuming that redBar's masks are already properly set)
greenBall.physicsBody?.collisionBitMask = GreenBallCategory | RedBallCategory | WallCategory //Collision will occur when GreenBall hits GreenBall, RedBall or hits a Wall

redBall.physicsBody?.categoryBitMask = RedBallCategory //Category is RedBall
redBall.physicsBody?.contactTestBitMask = GreenBarCategory | GreenBallCategory | WallCategory //Contact will be detected when RedBall make a contact with GreenBar , GreenBall or a Wall
redBall.physicsBody?.collisionBitMask = RedBallCategory | GreenBallCategory | WallCategory //Collision will occur when RedBall meets RedBall, GreenBall or hits a Wall

let borderBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
self.physicsBody = borderBody
self.physicsBody?.friction = 0
borderBody.contactTestBitMask = RedBallCategory | GreenBallCategory //Contact will be detected when red or green ball hit the wall
borderBody.categoryBitMask = WallCategory
borderBody.collisionBitMask = RedBallCategory | GreenBallCategory // Collisions between RedBall GreenBall and a Wall will be detected
我建议您阅读关于哪个是定义物理实体所属类别的掩码的文档:

场景中的每个物理体最多可以指定32个不同的对象 类别,每个类别对应于位掩码中的位。你定义 游戏中使用的掩码值。连同 collisionBitMask和contactTestBitMask属性,您可以定义 当你的游戏被通知时,物理实体会相互作用 这些相互作用的一部分

-定义哪些类别的实体会导致与当前物理实体的相交通知的掩码

当两个实体共享同一空间时,每个实体的类别遮罩为 通过执行逻辑测试,针对另一个身体的接触面具进行测试 和操作。如果其中一个比较结果为非零值,则 SKPhysicContact对象被创建并传递给物理世界的 代表。为获得最佳性能,仅在联系人掩码中设置 你感兴趣的互动

-定义哪些类别的物理体可以与该物理体碰撞的遮罩

当两个物理体相互接触时,可能发生碰撞。 将此实体的碰撞遮罩与其他实体的类别进行比较 通过执行逻辑AND操作屏蔽。如果结果为非零 值,则此实体受碰撞影响。每个机构都是独立的 选择是否要受其他实体的影响。对于 例如,您可以使用此选项来避免碰撞计算,因为碰撞计算会 对物体的速度作微不足道的改变

所以基本上,要建立所有这些,你应该问你自己一些事情,比如:

好的,我有一个绿色的球,一个红色的球,还有场景中的墙对象。我希望在哪些实体之间发生碰撞,或者何时注册联系人?我想要一个绿色和一个红色的球互相碰撞,并撞到墙上。没问题。我将首先正确设置类别,然后设置冲突位掩码,如下所示:

greenBall.collisionBitMask = GreenBallCategory | RedBallCategory | WallCategory; //greenBall will collide with greenBall, redBall and a wall
redBall.collisionBitMask = GreenBallCategory | RedBallCategory | WallCategory

wall.collisionBitMask = GreenBall | RedBall
现在,我想检测何时出现一些接触(在
didBeginContact
:方法中)。。。但是我不想得到关于所有可能接触的通知,而是只想得到关于球之间接触的通知(球和墙之间的接触将被忽略)。因此,让我们设置
contactTestBitMasks
来实现这一点:

greenBall.contactTestBitMask = GreenBallCategory | RedBallCategory;
redBall.contactTestBitMask = GreenBallCategory | RedBallCategory;
就这样。重要的是,当您不使用联系人检测时,不应设置
contactTestBitMask
。这是因为性能原因。如果您不需要冲突检测,并且只对检测联系人感兴趣,则可以设置
collisionBitMask=0

重要:

确保已设置Physical world的联系人代理,以便使用
didBeginContact
didEndContact
方法:

self.physicsWorld.contactDelegate = self; //where self is a current scene

希望这能有所帮助。

只想在此添加一点,即如果接触或碰撞无法正常工作,则需要确保在应用位掩码之前先指定physicsBody形状

不工作位掩码的示例:

        SKSpriteNode *bird = [SKSpriteNode spriteNodeWithImageNamed:@"bird1.png"];
        bird.name = @"bird";
        bird.physicsBody.categoryBitMask = birdCategory;
        bird.physicsBody.contactTestBitMask = wallCategory | scoreCategory;
        bird.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:bird.size.width/2.7];
        bird.position = CGPointMake(_mySize.width/3.0, 2*_mySize.height/3.0);
        [self addChild:bird];
工作一:

    SKSpriteNode *bird = [SKSpriteNode spriteNodeWithImageNamed:@"bird1.png"];
    bird.name = @"bird";
    bird.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:bird.size.width/2.7];
    bird.physicsBody.categoryBitMask = birdCategory;
    bird.physicsBody.contactTestBitMask = wallCategory | scoreCategory;
    bird.position = CGPointMake(_mySize.width/3.0, 2*_mySize.height/3.0);
    [self addChild:bird];

无论如何,这可能只是一个新手的错误,但我想在这里分享一下,因为这是导致我的工作不正常的原因。

回答太好了,非常感谢你花时间把这些都写出来。它工作得很好。“问问你自己这件事”这一部分明确地澄清了我的困惑。非常感谢你!如果你有超过32个呢?@Abcdefg你怎么能在didEnd函数中检测到冲突的结束?非常好的答案-非常感谢!为了这个话题挣扎了几天。你的“问你自己”部分是我见过的最好的解释。