SpriteKit:精灵之间没有碰撞检测。

时间:2015-03-22 02:11:09

标签: sprite-kit collision-detection

在SpriteKit中设置碰撞检测不是一件困难的事情,我之前已经做过了。尽管在其他项目中成功使用它并且有大量关于该主题的文档,但我无法在当前项目中使用它,而且我不知道为什么。

上下文非常简单。我将球体(SKSpriteNode)添加到背景Sprite中,然后用我的手指移动它们,期望它们在相互接触时检测碰撞。 (这不会发生)。

预期结果是检测到碰撞。

场景设置:

@interface GameScene () <SKPhysicsContactDelegate>
...
@implementation GameScene

// Collision BitMask
static const uint32_t planetCategory =  0x1 << 0;

场景也将自己设置为physicsWorld的委托

[self.physicsWorld setContactDelegate:self];

我给了我的场景只有一个碰撞位掩码,因为所有对象都属于同一类型,并且应该全部相互碰撞。我还设置了场景以符合SKPhysicsContactDelegate协议。

精灵配置:

#pragma mark Protocol Methods (For Adding Planets)
-(void)addSKPlanetDescriptorObject:(SKPlanetDescriptor *)object
{
    if (self.allowedNodes > 0){

        SKObject *node = [[SKObject alloc]initWithImageNamed:object.imageName];
        [node setDescriptor:object];

        // Set Physics
        [node.physicsBody setCategoryBitMask:planetCategory];
        [node.physicsBody setContactTestBitMask:planetCategory];
        [node.physicsBody setCollisionBitMask:planetCategory];

        [self.background addChild:node];
        [self.sceneObjects addObject:node];
        [node setPosition:self.pendingSpawnPoint];
        [self decreaseObjectCount];
    } else {
        [self indicateMinObjectCount];
    }
}

最后,初始化程序用于 SKObject SKSpriteNode 的子类

@implementation SKObject


-(instancetype)initWithImageNamed:(NSString *)name
{
    self = [super initWithImageNamed:name];
    if (self)
    {
        [self setPhysicsBody:[SKPhysicsBody bodyWithCircleOfRadius:self.size.width/2]];
        [self.physicsBody setAffectedByGravity:NO];
        [self.physicsBody setUsesPreciseCollisionDetection:YES];
        [self.physicsBody setDynamic:YES];
        [self.physicsBody setMass:1000];
    }
    return self;
}

我已尝试在init语句之外删除setPhysicsBody方法,我尝试更改位掩码,我尝试省略setCollisionBitmask等等,但我根本无法弄清楚为什么我&#39 ;没有任何碰撞。

我还添加了

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

如果检测到任何内容,请使用换行符通知我。但是这种方法永远不会被解雇。

2 个答案:

答案 0 :(得分:0)

使用这个简单的代码(只是尝试拖动精灵),这与你的非常相似,我让一切运行良好(使用iPhone 6模拟器)...请尝试此代码,看看这是否适合你:

#import "GameScene.h"
static const uint32_t planetCategory =  0x1 << 0;

@interface GameScene () <SKPhysicsContactDelegate>

@property (nonatomic,strong) SKSpriteNode *ball1;
@property (nonatomic,strong) SKSpriteNode *ball2;

@end

@implementation GameScene

-(void)didMoveToView:(SKView *)view {

    [self.physicsWorld setContactDelegate:self];

    SKSpriteNode *ball1 = [self createBall];

    // Set Physics
    [ball1.physicsBody setCategoryBitMask:planetCategory];
    [ball1.physicsBody setContactTestBitMask:planetCategory];
    [ball1.physicsBody setCollisionBitMask:planetCategory];
    ball1.position = CGPointMake(100,499);
    ball1.name = @"ball1";


    [self addChild:ball1];

    SKSpriteNode *ball2 = [self createBall];



    // Set Physics
    [ball2.physicsBody setCategoryBitMask:planetCategory];
    [ball2.physicsBody setContactTestBitMask:planetCategory];
    [ball2.physicsBody setCollisionBitMask:planetCategory];
    ball2.position = CGPointMake(100,123);
    ball2.name = @"ball2";


    [self addChild:ball2];


}

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    /* Called when a touch begins */

}

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{

    for (UITouch *touch in touches) {
        CGPoint location = [touch locationInNode:self];


        if([[self nodeAtPoint:location].name isEqualToString:@"ball1"]){

            [self childNodeWithName:@"ball1"].position = location;

        }
        if([[self nodeAtPoint:location].name isEqualToString:@"ball2"]){

            [self childNodeWithName:@"ball2"].position = location;


        }
    }
}

-(SKSpriteNode*) createBall{

    SKSpriteNode *ball = [[SKSpriteNode alloc] initWithImageNamed:@"balloon_large"];

    ball.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:ball.size.width/2];

    [ball.physicsBody setAffectedByGravity:NO];
    [ball.physicsBody setUsesPreciseCollisionDetection:YES];
    [ball.physicsBody setDynamic:YES];
    [ball.physicsBody setMass:1000];

    return ball;
}

-(void)update:(CFTimeInterval)currentTime {
    /* Called before each frame is rendered */
}

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

@end

如果您无法使用此代码段重现良好的结果,那么您可能需要检查代码的其他部分以找出导致这些问题的原因。但是,让我们先尝试一下,现在让我谈谈结果......

答案 1 :(得分:0)

这最终都是由于一个愚蠢的错误造成的。

要暂停我的游戏,我有一个名为BOOL isPaused的属性。这恰好也是SpriteKit用来暂停物理的属性。当我解开方法[self setIsPaused:YES];时,我无意中禁用了碰撞检测。我当时也未能正确地取消它,因为它认为它没有做任何事情。我现在知道它实际上是一个SpriteKit方法。

我希望这对其他人有帮助,如果他们偶然发现同样的问题。始终确保在您希望物理工作时启用isPaused属性(如果已使用)。