2017-07-18 59 views
3

我正在用SpriteKit创建一个游戏,它有两个物体之间的碰撞。设立机构后,我已经实现了didBegin(_contact:) moethod如下图所示:SKPhysics的扩展名联系人崩溃

func didBegin(_ contact: SKPhysicsContact) { 
    if contact.bodyA.categoryBitMask == 0 && contact.bodyB.categoryBitMask == 1 { 
     gameOver() 
    } 
} 

它完美地工作。

以后,当inspecrting此方法的文档,我发现:

The two physics bodies described in the contact parameter are not passed in a guaranteed order.

所以要在安全方面,我已经延长了SKPhysicsContact类与功能的互换双方之间的categoryBitMask机构如下:

extension SKPhysicsContact { 

    func bodiesAreFromCategories(_ a: UInt32, and b: UInt32) -> Bool { 
     if self.bodyA.categoryBitMask == a && self.bodyB.categoryBitMask == b { return true } 
     if self.bodyA.categoryBitMask == b && self.bodyB.categoryBitMask == a { return true } 
     return false 
    } 
} 

的问题是,当函数被调用,应用程序崩溃,并且我得到以下错误:

2017-07-18 13:44:18.548 iSnake Retro[17606:735367] -[PKPhysicsContact bodiesAreFromCategories:and:]: unrecognized selector sent to instance 0x60000028b950

2017-07-18 13:44:18.563 iSnake Retro[17606:735367] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[PKPhysicsContact bodiesAreFromCategories:and:]: unrecognized selector sent to instance 0x60000028b950'

+0

权力正确设置你的面具,这是一个很酷的扩展,但通常你只需要添加该类别一起掩盖以完全避免这个问题。 – Fluidity

+0

@Fluidity你的意思是将两个值都替换为'0 | 1'?如果是的话,这是完全不可能的,因为同一类别的两个物体之间的碰撞产生与来自两个不同类别的物体不同的作用 – Fayyouz

+1

否,请参阅我的答案。您将类别掩码添加到一起以获得唯一的总和。你必须设置你的面具在两个权力为此工作。 2 + 2总是等于4,并且2 + 4总是等于6,即使它是4 + 2 – Fluidity

回答

2

这显然是一个错误,因为在这里找到答案: https://stackoverflow.com/a/33423409/6593818

The problem is, the type of contact is PKPhysicsContact (as you've noticed), even when you explicitly tell it to be an SKPhysicsContact, and the extension is on SKPhysicsContact. You'd have to be able to make an extension to PKPhysicsContact for this to work. From this logic, we can say that no instance methods will work in SKPhysicsContact extensions at the moment. I'd say it's a bug with SpriteKit, and you should file a radar. Class methods still work since you call them on the class itself.

In the meantime, you should be able to move that method into your scene or another object and call it there successfully.

For the record, this is not a Swift-specific problem. If you make the same method in an Objective-C category on SKPhysicsContact you'll get the same crash.

您可以提交错误报告给苹果:

https://developer.apple.com/bug-reporting/

,并报告给社区:

https://openradar.appspot.com/search?query=spritekit

但是,您真正想要对您的代码执行的操作是,将类别遮罩一起添加到。然后检查总和(2 + 4和4 + 2总是等于6,无论bodyA和bodyB的顺序如何)。

这是你如何让唯一接触,如果你在两(2,4,8,16,等)

+0

这不是一个bug – Knight0fDragon

+0

也加入他们在一起是一个可怕的想法,你仍然不知道哪个机构是哪个,所以没有办法保证这个机构在 – Knight0fDragon

+0

@ Knight0fDragon这是一个错误。由于苹果糟糕的设计决定,因此破坏了应该工作的代码。这就像试图吃一个苹果,然后意识到这是一种塑料,而其他每一片水果都可以食用。塑料苹果需要“固定” – Fluidity

2

SKPhysicsContact是包装类PKPhysicsContact,要扩展SKPhysicsContact但在现实中,你需要扩展PKPhysicsContact(你不能这样做)

为了您的联系方式维持秩序,只是做:

let bodyA = contact.bodyA.categoryBitMask <= self.bodyB.categoryBitMask ? contact.bodyA : contact.bodyB 

let bodyB = contact.bodyA.categoryBitMask > self.bodyB.categoryBitMask ? contact.bodyA : contact.bodyB 

当你需要检查特定的节点通过这种方式,你知道什么节点,以打,所以

func didBegin(_ contact: SKPhysicsContact) { 
    if contact.bodyA.categoryBitMask == 0 && contact.bodyB.categoryBitMask == 1 { 
     gameOver() 
    } 
} 

成为

func didBegin(_ contact: SKPhysicsContact) { 

    let bodyA = contact.bodyA.categoryBitMask <= self.bodyB.categoryBitMask ? contact.bodyA : contact.bodyB 

    let bodyB = contact.bodyA.categoryBitMask > self.bodyB.categoryBitMask ? contact.bodyA : contact.bodyB 
    if bodyA.categoryBitMask == 0 && bodyB.categoryBitMask == 1 { 
     gameOver() 
    } 
} 

然后,您可以添加到您的代码,因为您现在知道个别的身体。

func didBegin(_ contact: SKPhysicsContact) { 

    let bodyA = contact.bodyA.categoryBitMask <= self.bodyB.categoryBitMask ? contact.bodyA : contact.bodyB 

    let bodyB = contact.bodyA.categoryBitMask > self.bodyB.categoryBitMask ? contact.bodyA : contact.bodyB 
    if bodyA.categoryBitMask == 0 && bodyB.categoryBitMask == 1 { 
     gameOver() 
     //since I know bodyB is 1, let's add an emitter effect on bodyB.node 
    } 
} 

顺便说一句,人谁看到这个答案,categoryBitMask 0不应该被解雇任何接触,你需要某种形式的IT价值的工作。这是一个超出作者问题范围的错误,所以我将它留在0和1处,因为这是他/她的代码正在做的事情,并且他声称它是有效的。

+0

这个(和documentaton)现在有更多的意义现在的额外信息 – Fluidity

+0

@流利性,只是添加评论,当你不明白的东西,我会详细说明它 – Knight0fDragon

+0

我呢,我们甚至去聊天一个几次。 – Fluidity