简体   繁体   中英

Collision detection in Sprite Kit

I'm using collision detection in Sprite Kit. It is working and preventing my sprites from crossing paths. However, I'm not getting notifications in didBeginContact: and I don't seem to have any control over how the physics engine responds when a collision occurs.

I have various cars (SKSpriteNodes) moving around following paths using the SKAction followPath:asOffset:orientToPath:duration:

Previously, if two cars crossed paths they would both just continue as normal with one driving over the other. To implement collision detection I have made the following changes...

Added this to my @interface:

<SKPhysicsContactDelegate>

Added this to my @implementation:

static const uint32_t carCategory = 0x1 << 0;

Added this in my init method:

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

I create my blue car:

- (void)addBlueCar
{
    _blueCar = [SKSpriteNode spriteNodeWithImageNamed:@"Blue Car.png"];
    _blueCar.position = CGPointMake(818.0, -50.0);
    _blueCar.name = @"car";
    [self addChild:_blueCar];

    CGSize contactSize = CGSizeMake(_blueCar.size.width - 5.0, _blueCar.size.height - 5.0);
    _blueCar.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:contactSize];
    _blueCar.physicsBody.categoryBitMask = carCategory;
    _blueCar.physicsBody.collisionBitMask = carCategory;
    _blueCar.physicsBody.contactTestBitMask = carCategory;
}

And I also create a red car:

- (void)addRedCar
{
    _redCar = [SKSpriteNode spriteNodeWithImageNamed:@"Red Car.png"];
    _redCar = CGPointMake(818.0, -50.0);
    _redCar = @"car";
    [self addChild: _redCar];

    CGSize contactSize = CGSizeMake(_blueCar.size.width - 5.0, _blueCar.size.height - 5.0);
    _redCar.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:contactSize];
    _redCar.physicsBody.categoryBitMask = carCategory;
    _redCar.physicsBody.collisionBitMask = carCategory;
    _redCar.physicsBody.contactTestBitMask = carCategory;
}

There are other cars as well, but I'm just using these two until I figure out what the problem is. I want to be notified of any collision between any two cars. That's why I'm just using a single category, carCategory.

The first problem is that I get no notifications. I have this yet it never logs anything to the console:

- (void)didBeginContact:(SKPhysicsContact *)contact
{
    NSLog(@"Contact");
}

The second problem is that when two cars cross paths they start nudging each other off course. This is ok, but I don't seem to able to manage any aspects of how the collision is handled. The bizarre thing is that nothing changes when I do this to both of my car creation methods:

- (void)addBlueCar
{
    _blueCar = [SKSpriteNode spriteNodeWithImageNamed:@"Blue Car.png"];
    _blueCar.position = CGPointMake(818.0, -50.0);
    _blueCar.name = @"car";
    [self addChild:_blueCar];

    CGSize contactSize = CGSizeMake(_blueCar.size.width - 5.0, _blueCar.size.height - 5.0);
    _blueCar.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:contactSize];
//    _blueCar.physicsBody.categoryBitMask = carCategory;
//    _blueCar.physicsBody.collisionBitMask = carCategory;
//    _blueCar.physicsBody.contactTestBitMask = carCategory;
}

Collision detection still works the same with those three lines commented out for both cars. This just doesn't seem right to me. Collision detection only ceases when I also comment out this line:

    _blueCar.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:contactSize];

So my main question is: why is the contactTest not reporting anything? My second question is: why is collision detection happening when I don't assign a categoryBitMask, collisionBitMask or contactTestBitMask to any car?

collisionBitMask 's default value is 0xFFFFFFFF (all bits set). Therefore the node will collide with each physicBody on the scene.

Just a small observation, perhaps you should setup your nodes and set the contact delegate in the scene's didMoveToView method.

If that doesn't solve it, any chance you can post some working code to github for debugging?

Something that helped me with this: Collisions and contacts are different things.

Collision is handled by the physics engine and setting collisionBitMask will determine which bodies collide and interact with each other in the physics world. By default, all your bodies will collide with each other, which kinda makes sense.

Contacts are events- when bodies make contact, will they create a notification that you can use in the delegate method to do more interesting things. If you have a ball you want to hit with a paddle, you want them to collide at a minimum. But if you have a ball moving through a cloud, you probably don't want them to collide in the physics world, but you might want to register the contact.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM