2017-07-18 96 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