将精灵添加到导致EXC_BAD_ACCESS的场景

时间:2018-10-12 20:27:27

标签: ios swift sprite-kit skspritenode

所以我找不到适合我问题的好答案。我正在iOS上创建SpriteKit游戏。我只是要给大家快速了解我的设置,然后再解决问题。我认为这是最好的解释方式。

设置:

基本上,在我的didMove(查看)方法中,我调用了两个帮助器函数:setupNodes()和setupLevel()。这些功能的作用是将不同的场景和SKSpriteNodes加载到内存中,然后将它们添加到场景中。这是我用来执行此操作的代码:

 func setupNodes(){
    doubleVent = (loadForegroundOverlayTemplate("DoubleVent").copy()  as! SKSpriteNode)
}

func loadForegroundOverlayTemplate(_ fileName: String) -> SKSpriteNode{
    let overlayScene = SKScene(fileNamed: fileName)!
    let overlayTemplate = overlayScene.childNode(withName: "ForegroundOverlay")!.copy() as! SKSpriteNode
    return overlayTemplate 
}

现在它存储场景,该场景是名为“ ForegroundOverlay”的SKNode的子级。然后,我将其传递给名为“ createForegroundOverlay()”的函数,如下所示:

let overlaySprite = doubleVent
createForegroundOverlay(doubleVent)

然后“ createForegroundOverlay”将存储在doubleVent中的SKSpriteNode添加到场景中,如下所示:

 func createForegroundOverlay(_ overlayTemplate: SKSpriteNode) {
    let foregroundOverlay = overlayTemplate.copy() as? SKSpriteNode
    lastOverlayPosition.x = lastOverlayPosition.x + (lastOverlayWidth + ((foregroundOverlay?.size.width)!)/2)

    lastOverlayWidth = (foregroundOverlay?.size.width)!/2.0
    foregroundOverlay?.position = lastOverlayPosition

    //TESTING PURPOSES
    if TESTING_NODE_POS{
        print("The last overlay position x:\(lastOverlayPosition.x), y:\(lastOverlayPosition.y)")
        print("The last overlay width is \(lastOverlayWidth)")
        print("Adding a foreground overlay \(count)")
        count += 1
    }

    //TESTING PURPOSES
    if TESTING_BOX_OUTLINE {
        let foregroundPos = foregroundOverlay?.position
        let boxLocation = foregroundOverlay?.childNode(withName: "Box1")?.position
        if boxLocation != nil {
            print("The location of the box \(String(describing: boxLocation))")
            print("The foregroundLocation is \(String(describing: foregroundPos))")
            print("last overlay position is \(lastOverlayPosition)")
        }
    }

    //add the foreground overlay as a child of the foreground node
    fgNode.addChild(foregroundOverlay!)

}

用于定位的变量-lastOverlayPosition,lastOverlayWidth等-只是我的GameScene类的属性,用于了解在何时何地添加所传递的叠加层。

fgNode是我从GameScene.sks文件中存储的节点,如下所示:

let worldNode = self.childNode(withName: "World")!
    bgNode = worldNode.childNode(withName: "Background")!
    bgCityNode = worldNode.childNode(withName: "BackgroundCity")
    cityBGOverlayTemplate = (bgCityNode.childNode(withName: "Overlay")!.copy() as! SKNode)
    cityOverlayWidth = bgCityNode.calculateAccumulatedFrame().width
    backgroundOverlayTemplate = (bgNode.childNode(withName: "Overlay")!.copy() as! SKNode)
    backgroundOverlayWidth = backgroundOverlayTemplate.calculateAccumulatedFrame().width
    fgNode = worldNode.childNode(withName: "Foreground")!

这也是在我的setupNodes()方法中完成的。

问题:

所以也许你们中的一些人已经看到了问题,但是问题是当我启动游戏时它崩溃了,并且我得到了消息:

  

“线程1:EXC_BAD_ACCESS :(代码= 1,地址= 0x78)”

每当发生崩溃时,它都是完全相同的消息。我想我知道错误在说什么。基本上,有一个指针指向内存中的某个位置(0x78),那里没有任何内容。因此,取消引用该指针显然会导致错误。这是我感到困惑的地方...这只会发生大约50%的时间。当我运行并构建项目时,它每次都会成功构建,然后崩溃50%的时间并显示该错误消息。其次,这在一开始就发生了。这对我来说很奇怪,因为如何可以释放一些内存,导致游戏一开始出现错误的指针。另外,如果崩溃不是在启动时发生的,那么崩溃就永远不会发生,除非在显示游戏结束场景之后我重新加载场景,这与正在重新启动的游戏基本相同。

一段时间后,我将问题缩小为一行代码:

fgNode.addChild(foregroundOverlay!)

如果我将这一行注释掉,则不会发生崩溃(我尝试构建并运行50次)。问题一定出在前景色变量上,该变量是使用本讨论的“设置”部分中的代码设置的。所以我不知道如何解决这个问题...任何想法?

P.S。可能还值得注意的是,以这种方式将孩子添加到场景中时,仅当我升级到xCode 10.0并考虑使用僵尸时才成为一个问题,但我认为这样做没有帮助,因为崩溃仅发生在游戏的发布。

如果我不清楚在任何地方,请告诉我。

0 个答案:

没有答案