SKSpriteNode 无法检测到与两个 bodyWithEdgeLoopF​​romPath 主体的碰撞

Posted

技术标签:

【中文标题】SKSpriteNode 无法检测到与两个 bodyWithEdgeLoopF​​romPath 主体的碰撞【英文标题】:SKSpriteNode can't detect collision with two bodyWithEdgeLoopFromPath bodies 【发布时间】:2015-01-30 03:19:10 【问题描述】:

我使用 bodyWithEdgeLoopF​​romPath 创建了两个对象。但是当我通过方法检查碰撞时 - (void)didBeginContact:(SKPhysicsContact *)contact。它不工作。

对象 1: UIBezierPath *paddleLeftPath = [UIBezierPath bezierPath];

[paddleLeftPath moveToPoint:CGPointMake(-19,17)];
[paddleLeftPath addLineToPoint:CGPointMake(20,17)];
[paddleLeftPath addLineToPoint:CGPointMake(10,6)];
[paddleLeftPath addLineToPoint:CGPointMake(17,-7)];
[paddleLeftPath addLineToPoint:CGPointMake(6,-19)];
[paddleLeftPath addLineToPoint:CGPointMake(-6,-20)];
[paddleLeftPath addLineToPoint:CGPointMake(-17,-11)];
[paddleLeftPath addLineToPoint:CGPointMake(-13,6)];

[paddleLeftPath closePath];

objectRocket = [[NodeRocket alloc] initWithWithFile:@"main0.png" scale:0.5 atPosition:CGPointMake(CGRectGetMidX(self.frame),110)];
objectRocket.name = @"Rocket";
objectRocket.physicsBody.dynamic = NO;
objectRocket.physicsBody.usesPreciseCollisionDetection = YES;
objectRocket.physicsBody.categoryBitMask = rocketCategory;
objectRocket.physicsBody.collisionBitMask =  meteorCategory;
objectRocket.physicsBody.contactTestBitMask =  meteorCategory;
objectRocket.zPosition = 10;
objectRocket.physicsBody.allowsRotation = NO;
[self addChild:objectRocket];    

对象 2: SKNode* meteorPair = [SKNode 节点]; meteorPair.position = CGPointMake(0, 0); 流星对.zPosition = 10;

    NSInteger scaleValue = (arc4random() % 8) + 1;

    meteorTexture = [SKTexture textureWithImageNamed:[NSString stringWithFormat:@"monster%d.png",(int)scaleValue]];

    [meteorTexture setFilteringMode:SKTextureFilteringNearest];

    if (pointDrop.x > self.size.width - meteorTexture.size.width/2 - 10)
    
        pointDrop.x = self.size.width - meteorTexture.size.width/2 - 10;
    
    else if (pointDrop.x < meteorTexture.size.width/2 + 10)
    
        pointDrop.x = meteorTexture.size.width/2 + 10;
    

    CGFloat x = (arc4random() % 2) + 0.5;

    CGFloat distanceToMove = self.frame.size.height - 115 - objectUFO.size.height/2;
    SKAction* moveMeteor = [SKAction moveByX:0 y:-distanceToMove duration:x/100.0 * distanceToMove];
    SKAction* removeMeteor = [SKAction removeFromParent];
    moveMeteorAndRemove = [SKAction sequence:@[moveMeteor, removeMeteor]];

    SKSpriteNode* meteorObject = [SKSpriteNode spriteNodeWithTexture:meteorTexture];
    [meteorObject setScale:0.55];
    meteorObject.position = CGPointMake(pointDrop.x, pointDrop.y - objectUFO.size.height/2 );

    UIBezierPath *paddleLeftPath = [UIBezierPath bezierPath];

    [paddleLeftPath moveToPoint:CGPointMake(-22,28)];
    [paddleLeftPath addLineToPoint:CGPointMake(21,28)];
    [paddleLeftPath addLineToPoint:CGPointMake(17,-30)];
    [paddleLeftPath addLineToPoint:CGPointMake(-18,-30)];
    [paddleLeftPath closePath];
    meteorObject.name = [NSString stringWithFormat:@"monster%d.png",(int)scaleValue];
    meteorObject.physicsBody.dynamic = NO;
    meteorObject.physicsBody.usesPreciseCollisionDetection = YES;
    meteorObject.physicsBody.categoryBitMask = meteorCategory;        
    [meteorPair addChild:meteorObject];

    [meteorPair runAction:moveMeteorAndRemove];
    meteorPair.name = @"meteor pair";

    [self addChild:meteorPair];
     meteorObject.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromPath:paddleLeftPath.CGPath];    

请帮助我。我做错了什么?

【问题讨论】:

查看文档,两个静态(基于边缘)的物体永远不会产生碰撞。同样使用移动动作绕过物理模拟,使用 applyImpulse/Force 来移动动态物理体。 我让物体meteorObject坠落到与objectRocket发生碰撞。但是方法 didBeginContact 不起作用。 我将 bodyWithEdgeLoopF​​romPath 更改为 bodyWithPolygonFromPath。和meteorObject.physicsBody.dynamic = YES。他们可能会发生冲突,但方法 didBeginContact 仍然无法正常工作。 你设置了collisionDelegate吗?还要检查类别等位掩码,它们经常被误解,它们必须双向(即流星和火箭在一个主体中,火箭和流星在另一个主体中 - 仅省略其中一个位掩码不会产生碰撞)。 【参考方案1】:

你为 SKScene 的物理世界设置了 contactDelegate 了吗?也许您错过了它,然后 didBeginContact 从未被调用过。 在你的游戏场景上试试这个

self.physicsWorld.contactDelegate = self

【讨论】:

【参考方案2】:

看起来你在分配物理体之前设置了一堆参数。

我是 SKPhysics 的新手,但从所有示例中可以看出,当您创建节点时,它带有一个 nil/null 物理体。

要明确。 SKSpriteNode* meteorObject = [SKSpriteNode spriteNodeWithTexture: ... meteorObject.physicsBody.dynamic = NO; meteorObject.physicsBody.usesPreciseCollisionDetection = YES; meteorObject.physicsBody.categoryBitMask = meteorCategory; ... meteorObject.physicsBody = [SKPhysicsBody bodyWithEdgeLoopF​​romPath:

必须是:-

SKSpriteNode*meteorObject = [SKSpriteNode spriteNodeWithTexture: ... meteorObject.physicsBody = [SKPhysicsBody bodyWithEdgeLoopF​​romPath: meteorObject.physicsBody.dynamic = NO; meteorObject.physicsBody.usesPreciseCollisionDetection = YES; meteorObject.physicsBody.categoryBitMask = meteorCategory; ...

【讨论】:

以上是关于SKSpriteNode 无法检测到与两个 bodyWithEdgeLoopF​​romPath 主体的碰撞的主要内容,如果未能解决你的问题,请参考以下文章

如何加入两个碰撞的 SKSpriteNode

didBegin 未检测到两个 SKSpriteNode 之间的接触

无法点击 SKSpriteNode - 未检测到触摸 ios

如何检测 SKSpriteNode 接触但不反应?

未检测到 SkSpriteNode 冲突

检测用户何时点击 SKSpriteNode