使用所需的 init(nscoder) 时从代码设置物理体

setting up physics body from code when using required init(nscoder)

我正在尝试利用 init?(coder aDecoder: NSCoder) 函数,以便我可以在我的 sks 文件中子类化精灵。

我可以在 sks 文件中设置物理体,但它不适用于我正在使用的也有圆角的矩形精灵。由于圆角,在使用 init 函数之前,我在代码中设置了 physicsbody,并将宽度设置为略小于正方形的宽度(这样当我的英雄滑出正方形时,没有间隙圆角是..

我知道我可以使用 alpha mask physics body 来获得相同的效果,除了这个,当我的英雄在方块上时似乎有 1 px'ish 的差距,看起来并不不错。

想知道为什么我不能设置物理体,以及我如何做或绕过它?

感谢您的帮助!!!

更新:

    required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    if let p = userData?.value(forKey: "col") as? String {
        setup(p)
        print("working")
    }
}
func setup(_ col: String) {
    setupPhysics()
    //allSprites.append(self)

在 setupPhysics 中我有:

override func setupPhysics() {
    physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: frame.width - 4, height: frame.height - 1))
...more code...
}

这是我的精灵代码,我在 sks 文件中正确设置了它...

我注释掉了 allSprites 的附加部分,这样我就可以证明它不起作用。取消注释后,精灵被添加到 allSprites,然后在我的场景文件中的 didMove 函数中,它循环遍历 allSprites 并运行 setupPhysics():

  func setup(_ col: String) {
    //setupPhysics()
    allSprites.append(self)

// scene file
    func setupAllSpritesPhysics() {
    for sprite in allSprites { sprite.setupPhysics() }
}

@Knight0fDragon :

您提到这是一个丑陋的修复程序。我不同意它不会以 'correct' 方式工作的事实。目前我没有足够的精灵来导致场景加载出现任何延迟。如果是这样的话,我可以在将来研究一下。

我承认我没有尝试过你提到的方法,因为我不想为我创建的每个精灵创建一个子节点来解决这个问题,即使它有效。尽管如此,我还是很感激你的建议。

为了使它与 SKS 文件一起工作,我将添加一个 child SKNode,其尺寸为您想要的 body,然后在自定义 class 代码中,执行

required init(coder aDecoder:NSCoder){
    super.init(coder:aDecoder)
    if let child = childNode(withName:"child"), let physicsBody = child.physicsBody{
       self.physicsBody = physicsBody
       child.removeFromParent()
    }
}

我们在这里所做的是将物理 body 从 child 转移到 parent,然后关闭 child。这使我们的代码更加动态,并使设计与功能分开。

好吧,来自 apple 的漂亮小虫子。

发生的事情是 physicsWorld 在 NSCoder 发生时不存在,而不是将物理 body 附加到精灵 body 到世界中,当它确实存在时,它决定缓存位于 SKS 文件中的那个,这就是它不起作用的原因。

因此,解决此问题的一个非常方便的方法是实现一个 worldNode(无论如何,这样做是一种很好的做法,特别是如果你想创建一个暂停屏幕),只需将其删除,然后再将其添加回去在场景加载期间:

class GameScene: SKScene,SKPhysicsContactDelegate {
    lazy var worldNode : SKNode = { self.childNode(withName:"//worldNode")!}()

    override func sceneDidLoad() {
        worldNode.removeFromParent()
        addChild(worldNode)
    }
}