首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SKPhysicsContact崩溃的扩展

SKPhysicsContact崩溃的扩展
EN

Stack Overflow用户
提问于 2017-07-18 10:55:55
回答 2查看 74关注 0票数 3

我正在创建一个与SpriteKit的游戏,它有两个身体之间的碰撞。在设置了主体之后,我实现了didBegin(_contact:)方法,如下所示:

代码语言:javascript
复制
func didBegin(_ contact: SKPhysicsContact) {
    if contact.bodyA.categoryBitMask == 0 && contact.bodyB.categoryBitMask == 1 {
        gameOver()
    }
}

而且效果很好。

稍后,在检查此方法的文档时,我发现了以下内容:

在接触参数中描述的两个物理体不以保证的顺序传递。

因此,为了安全起见,我将SKPhysicsContact类扩展为一个函数--在两个主体之间交换categoryBitMask,如下所示:

代码语言:javascript
复制
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 Retro17606:735367 -PKPhysicsContact bodiesAreFromCategories:和::未识别的选择器发送到实例0x60000028b950 2017-07-18 13:44:18.563 iSnake Retro17606:735367 *终止应用程序由于未被识别的异常'NSInvalidArgumentException',原因:'-PKPhysicsContact bodiesAreFromCategories:和::未识别的选择器发送到实例0x60000028b950‘

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-07-18 12:03:58

这显然是一个bug,在这里回答:https://stackoverflow.com/a/33423409/6593818

问题是,联系人的类型是PKPhysicsContact (正如您已经注意到的),即使您明确告诉它是SKPhysicsContact,并且扩展位于SKPhysicsContact上。您必须能够对PKPhysicsContact进行扩展才能工作。根据这个逻辑,我们可以说,目前没有实例方法在SKPhysicsContact扩展中工作。我想说这是SpriteKit的一个bug,你应该设置一个雷达。类方法仍然工作,因为您在类本身上调用它们。 同时,您应该能够将该方法移动到您的场景或其他对象中,并成功地将其调用到其中。 请注意,这并不是一个针对Swift的问题。如果您在SKPhysicsContact上的Objective类中使用相同的方法,您将得到相同的崩溃。

你可以向苹果提交一份错误报告:

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

并向社会报告:

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

但是,您真正想要对代码做的是将类别掩码添加到一起。然后检查和(2 +4和4+2总是等于6,而不考虑bodyA和bodyB顺序)。

这就是你如何获得独特的联系人,如果你正确地设置你的面具的力量二(2,4,8,16等)

票数 2
EN

Stack Overflow用户

发布于 2017-07-18 11:57:12

SKPhysicsContactPKPhysicsContact的包装类,您正在扩展SKPhysicsContact,但实际上您需要扩展PKPhysicsContact (这是您做不到的)

要在您的联系方法中保持顺序,只需:

代码语言:javascript
复制
let bodyA = contact.bodyA.categoryBitMask <= self.bodyB.categoryBitMask ? contact.bodyA : contact.bodyB

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

这样,当您需要检查某个特定节点时,您知道要访问哪个节点,因此

代码语言:javascript
复制
func didBegin(_ contact: SKPhysicsContact) {
    if contact.bodyA.categoryBitMask == 0 && contact.bodyB.categoryBitMask == 1 {
        gameOver()
    }
}

化作

代码语言:javascript
复制
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()
    }
}

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

代码语言:javascript
复制
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不应该触发任何联系人,您需要在其中有某种价值才能工作。这是一个超出作者问题范围的bug,所以我把它放在0和1,因为这是他/她的代码所做的,他(S)声称它可以工作。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45164773

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档