【问题标题】:My game is crashing after comes back from GameOverScene从 GameOverScene 回来后我的游戏崩溃了
【发布时间】:2016-01-20 01:58:52
【问题描述】:

我正在创建我的第一个游戏,从 GameOverScene 回来后它崩溃了。这是给我错误的部分:

//  GameScene.swift
//  Test_Crash_1


import SpriteKit

struct global {

    static var wheelRotPlat2 = SKShapeNode(circleOfRadius: 400)
    static var button : SKShapeNode = SKShapeNode()
    static var actualPlayer : String = String()
    static let btnNextPlayer = SKShapeNode(circleOfRadius: 70)
}

class GameScene: SKScene {

    deinit {
        print("The GameScene has been removed from memory")
    }


    override func didMoveToView(view: SKView) {

        let buttonDice = SKShapeNode(rectOfSize: (CGSizeMake(40,40)), cornerRadius: 5)
        global.button = buttonDice
        global.button.position = CGPoint(x: (CGRectGetMidX(self.frame)-400), y:(CGRectGetMidY(self.frame)-350))
        global.button.fillColor = UIColor(red: 0.2, green: 1.0, blue: 0.2, alpha: 0.8)
        global.button.name = "button"
        global.button.zPosition = 1
        addChild(global.button)

        global.wheelRotPlat2.addChild(global.btnNextPlayer)
        global.btnNextPlayer.name = "btnNextPlayer"
    } // end didMoveToView


    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        //func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {

        let touch = touches //as!  Set<UITouch>
        let location = touch.first!.locationInNode(self)
        let node = self.nodeAtPoint(location)

        if (node.name == "button") {

            self.removeAllActions()
            self.removeAllChildren()

            let reveal = SKTransition.flipHorizontalWithDuration(0.5)
            let gameOverScene = GameOverScene(size: self.size, player: global.actualPlayer)
            self.view?.presentScene(gameOverScene, transition: reveal)

        }
    } // End func touchesBegan

} // end GameScene

还有 GameOverScene 文件:

//  GameOverScene.swift
//  Test_Crash_1



import Foundation
import SpriteKit

class GameOverScene: SKScene {

    init(size: CGSize, player: String) {

        super.init(size: size)

        backgroundColor = SKColor.whiteColor()

        runAction(SKAction.sequence([
            SKAction.waitForDuration(3.0),
            SKAction.runBlock() {


                let reveal = SKTransition.flipHorizontalWithDuration(0.5)
                let scene = GameScene(size: size)
                self.view?.presentScene(scene, transition:reveal)

            }
        ]))

    } // end init(size


    required init(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
} // end GameOverScene

这个错误是众所周知的:

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Attemped to add a SKNode which already has a parent:  SKShapeNode  name:'btnNextPlayer'

此示例只有一个绿色按钮,可将我带到 GameOverScene。当它返回时游戏崩溃。

我不明白为什么会发生这种情况。 谁能告诉我为什么会发生这种情况以及如何解决?

【问题讨论】:

  • 除了 KnightOfDragon 的回答和我对他的问题的评论之外,您在 GameOverScene 中有一个保留周期。您不能像在闭包中那样使用 self 。你应该使用弱或无主的自我。搜索关于那个...

标签: ios swift crash sprite-kit


【解决方案1】:

错误告诉您发生了什么,您正在将一个节点添加到另一个节点,但该节点已经有一个父节点。这就是为什么使用全局变量是一个坏主意并且几乎不应该使用的原因。您有一个全局按钮。它附加到 GameScene,让我们调用 GameScene1。然后你打电话给Gameover。现在你调用了一个新的 GameScene,叫做 GameScene2。由于诸如全局变量之类的原因,您没有正确管理内存,因此 GameScene1 仍然存在。 Well 按钮仍然附加到 GameScene1,所以当你尝试将它添加到 GameScene2 时,XCode 会说“不,这个节点有一个父节点,去修复你的东西”。尽量不要使用全局数据,这样的问题应该会少一些。

编辑: 正如@Whirlwind 指出的那样,问题出在引起问题的全局项目global.wheelRotPlat2 中。

global.wheelRotPlat2.addChild(global.btnNextPlayer) 每次将 GameScene 移动到视图时都会被调用,并且由于您在杀死第一个场景时永远不会从其父级中删除 btnNextPlayer,所以当您创建第二个场景时,@987654325 @ 将尝试再次重新附加到相同的父级 (global.wheelRotPlat2),这会导致您的问题。

【讨论】:

  • @KnightOfDragon 一般来说,你说的是真的。但在这种情况下,如果仔细观察,按钮并没有添加到场景中。它被添加到另一个节点(wheelRotPlat2),该节点也没有添加到场景中。所以即使场景被正确释放,在这种情况下,也会出现同样的问题。我可以写一个答案来解释一切,但我很确定你明白我在说什么。另外,你有我的支持,因为你总体上是对的,而且这些都是很好的做法。
  • 你在说什么? addChild(global.button) 在 didmovetoview 中
  • 哦,该死的,哈哈,他的代码让人困惑,哈哈。在那种情况下,他做了一个本地人
  • @KnightOfDragon 那个按钮 (global.button) 被添加到场景中,并且它的 parent 属性将在场景的 deinit 中设置为 nil。该问题与另一个节点(btnNextPlayer)有关。这就是我要说的。
  • @KnightOfDragon 游戏场景在这种情况下将被正确释放,并且在 GameScene 的 deinit 上 global.button.parent 属性将设置为 nil。全局变量是这里的问题,而不是内存管理和保留周期。
猜你喜欢
  • 2020-06-14
  • 1970-01-01
  • 1970-01-01
  • 2012-05-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多