objective-c – 我的播放器以外的物理实体在碰撞时不会调用didBeginContact

在我的游戏中,我有4个位掩码,一切都已设置好,但只有当第一个位掩码(playerCategory)与某些东西发生碰撞时才会调用didBeginContact.如果3与4发生碰撞,即使我设置了contactTestBitMask以使它们发生碰撞,也没有任何反应.

myscene.h

    self.physicsWorld.gravity = CGVectorMake(0.0, -2.45);
    self.physicsWorld.contactDelegate = self;

    self.player = [SKSpriteNode spriteNodeWithColor:[SKColor blueColor] size: CGSizeMake(10.0, 20.0)];
    self.player.position = CGPointMake(20.0, self.frame.size.height);
    self.player.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:self.player.size];
    self.player.physicsBody.affectedByGravity = YES;
    self.player.physicsBody.dynamic = YES;
    self.player.physicsBody.categoryBitMask = playerCategory;
    self.player.physicsBody.contactTestBitMask = enemyCategory;
    self.player.physicsBody.collisionBitMask = tileCategory;
    [self.gameNode addChild:self.player];

    [...]

- (void) swipeRightHandler:(UISwipeGestureRecognizer *) recognizer {
    NSLog(@"swipe right");
    SKSpriteNode *attackRect = [SKSpriteNode spriteNodeWithColor:[SKColor redColor] size:CGSizeMake(40, 5)];
    attackRect.position = CGPointMake(self.player.position.x + 10, self.player.position.y);
    attackRect.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:attackRect.size];
    attackRect.physicsBody.categoryBitMask = attackCategory;
    attackRect.physicsBody.contactTestBitMask = 255;
    attackRect.physicsBody.collisionBitMask = enemyCategory;
    attackRect.physicsBody.affectedByGravity = NO;
    attackRect.physicsBody.dynamic = NO;
    [self.gameNode addChild:attackRect];
    [attackRect runAction:[SKAction moveBy:CGVectorMake(250, 0) duration:1.0] completion:^{
        [attackRect removeFromParent];
    }];
}

RandomLevelGenerator.m:

        SKSpriteNode *enemy = [SKSpriteNode spriteNodeWithColor:[SKColor greenColor] size:CGSizeMake(20, 20)];
        enemy.position = CGPointMake(visual_x, FLOOR_X + arc4random_uniform(MAX_Y - FLOOR_X));
        enemy.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:enemy.size];
        enemy.physicsBody.categoryBitMask = enemyCategory;
        enemy.physicsBody.contactTestBitMask = playerCategory | attackCategory;
        enemy.physicsBody.collisionBitMask = attackCategory;
        enemy.physicsBody.affectedByGravity = NO;
        enemy.physicsBody.dynamic = NO;
        [self.scene.gameNode addChild:enemy];

LevelGenerator.h:

static const uint32_t playerCategory    =   0x1 << 0;
static const uint32_t tileCategory      =   0x1 << 1;
static const uint32_t enemyCategory     =   0x1 << 2;
static const uint32_t attackCategory    =   0x1 << 3;

MyScene.m:

SKPhysicsBody *firstBody, *secondBody;

if(contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask)
{
    firstBody = contact.bodyA;
    secondBody = contact.bodyB;
} else {
    firstBody = contact.bodyB;
    secondBody = contact.bodyA;
}
NSLog(@"%d - %d", firstBody.categoryBitMask, secondBody.categoryBitMask);

最后一个NSLog,只打印1 – x,从不打印3 – x.我也试过允许其他碰撞,我不能让它们中的任何一个碰撞.

最佳答案 如果ANDed的两个实体的categoryBitMask为零,则它们不会生成联系事件.例如,这发生在playerCategory(1)和enemyCategory(4):1& 4 = 0< ==在玩家和敌人之间不会产生任何联系事件.在这种情况下,它甚至不会检查contactBitMask标志. 如果您希望两个实体生成联系事件,则它们都必须设置相同的类别位掩码标记. categoryBitMask的默认值为0xFFFFFFFF,以便所有实体可以相互联系.与collisionBitMask相同,因为通常您希望所有实体默认联系并发生碰撞. 在大多数情况下,您真正​​需要修改的唯一位掩码是contactBitMask,其默认值为0,表示默认情况下不会生成任何联系事件(以提高性能). 只更改仅改变contactBitMask的其他位掩码是不够的. 例如,当您想要接触事件但没有碰撞反馈时(=碰撞物体接触时速度/位置的变化),请确保这些物体的collisionBitMask ANDed一起为0.这允许物体生成接触事件,但是穿过对方.用于创建触发器,即当玩家进入某个区域时,您可以让他通过但也会触发游戏事件. 或者当你想为两个不同类别的身体使用相同的联系人位掩码时,他们只应该与共享相同类别的其他身体发生碰撞/接触 – 即常规和“幽灵”角色应该与游戏中的其他一切具有相同的联系行为除了他们不应该与他们的有形(非鬼)同行接触/碰撞.在这种情况下,对两个主体使用相同的contactBitMask和collisionBitMask.然后在categoryBitMask中为所有其他类别设置所有标志,但不要为表示物理实体和重影实体的两个类别设置标志.即如果物理类别为2且ghost类别为8,则categoryBitMask应为:0xFFFFFFFF – 2 – 8 = 0xFFFFFFF5(低8位将为:11110101) 长话短说:categoryBitMask标志应该从0xFFFFFFFF清除(而不是设置为特定位),以便特定类别中的各个主体不会相互联系但仍然与所有其他主体联系.

点赞