SceneKit在场景内存泄漏之间切换

时间:2019-01-27 09:47:28

标签: swift memory-leaks scenekit

我有两个没有任何节点和照相机的空白scnscene对象:

func setupScenes() {
   scnView = SCNView(frame: self.view.frame)
   self.view.addSubview(scnView)

   gameScene = SCNScene(named: "/MrPig.scnassets/GameScene.scn")
   splashScene = SCNScene(named: "/MrPig.scnassets/SplashScene.scn")
   scnView.scene = splashScene
}

两种显示每个场景的方法:

func startSplash() {
    gameScene.isPaused = true
    let transition = SKTransition.doorsOpenVertical(withDuration: 1.0)
    scnView.present(splashScene, with: transition, incomingPointOfView: nil, completionHandler: {
      self.gameState = .tapToPlay
      self.setupSounds()
      self.splashScene.isPaused = false
    })
  }

  func startGame() {
    splashScene.isPaused = true
    let transition = SKTransition.doorsOpenVertical(withDuration: 1.0)
    scnView.present(gameScene, with: transition, incomingPointOfView: nil, completionHandler: {
      self.gameState = .playing
      self.setupSounds()
      self.gameScene.isPaused = false
    })
  }

以及用于在场景之间切换的触摸手势:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        if gameState == .tapToPlay {
            startGame()
        } else {
            startSplash()
        }
    }

每次触摸屏幕时,屏幕上都会出现第一个或第二个场景,并且我习惯了〜80Mb的RAM。 经过10次接触后,已经使用了500MB的RAM。

我不明白为什么会这样?

2 个答案:

答案 0 :(得分:0)

代码中明显的问题是,每次调用startGame()和startSplash()方法时,带有闭包的嵌套函数都会捕获具有强引用的“自我”。

  

有关强引用和弱引用以及ARC的一些信息。

首先,您应该执行以下操作:

func startSplash() {
    gameScene.isPaused = true
    let transition = SKTransition.doorsOpenVertical(withDuration: 1.0)
    scnView.present(splashScene, with: transition, incomingPointOfView: nil, completionHandler: { [weak self] in
        guard let self = self else { return }
        self.gameState = .tapToPlay
        self.setupSounds()
        self.splashScene.isPaused = false
    })
}

func startGame() {
    splashScene.isPaused = true
    let transition = SKTransition.doorsOpenVertical(withDuration: 1.0)
    scnView.present(gameScene, with: transition, incomingPointOfView: nil, completionHandler: { [weak self] in
        guard let self = self else { return }
        self.gameState = .playing
        self.setupSounds()
        self.gameScene.isPaused = false
    })
}

第二,尽量不要使用touchesBegan方法,这可能会导致一些副作用。

希望有帮助!

答案 1 :(得分:0)

我遇到了完全相同的问题,无法找到原因,但是我想这与spritekit有关,特别是当您将Metal和Scenekit一起使用时。参见scenekit spritekit memory leak。 present(场景...)来自spritekit。我想出的唯一解决方案是直接设置场景和SCNView的视点,而不是通过present(...)方法。