Swift: release GameScene after moving to a new scene?

So, I read a few questions on this question, but most of them are in Objective-C, and I did not find this address / answer directly. I am new to programming, so please explain all the suggestions in detail.

I need to understand how to free my GameScene after the game is completed. The reason I need to do this is because after the game I switch to the new SKScene (playing backstage), and when I switch back to my GameScene, either GameScene is not reset completely, or I generate a new GameScene every time .

I say this because the frames per second drop every time I get the game and go back to GameScene, so if I do enough, I can no longer play the game. This is problem.

I don’t understand why this is happening, because when I go to my game on stage, I delete everything from my GameScene:

self.viewController!.performSegueWithIdentifier("goToGameOver", sender: nil) self.removeAllChildren() self.removeAllActions() self.scene?.removeFromParent() 

I also read here: After closing the SKScene, the memory remains high , that deleting the SKView that contains the SKScene frees up the SKScene, so when both my GameScene and the game over the scenes are left, I delete BOTH views from their supervisors as follows:

 override func viewDidDisappear(animated: Bool) { print("its gone") self.view.removeFromSuperview() } 

But nothing affects the decrease in the number of frames per second, and the game continues to lag. I don’t understand what I’m doing, and I can’t say whether playing over the stage is a problem, or I’m just not releasing GameScene.

How to free up GameScene? What else should I do?

EDIT:

My count and draws counter stays pretty much the same every time I go to GameScene, so that doesn't seem like a problem. I tried to check if deinit was called when switching between scenes (I had no deinit before) using this in the GameScene class:

 } //<**End of GAMESCENE** deinit { print("Deinit was called") } 

And nothing is printed, so deinit not called.

EDIT 2:

@alex_p This is what I have in my GameViewController-

 class GameViewController: UIViewController, SKProductsRequestDelegate, SKPaymentTransactionObserver { var scene1: GameScene? var scene2: GameScene? var skView: SKView? // Action to present next Scene @IBAction func nextSceneAction(sender: AnyObject) { print("Next scene") // Create new GameScene object scene2 = GameScene(fileNamed:"GameScene") // Present scene2 object that replace the scene1 object skView!.presentScene(scene2) //ERROR ON THIS LINE scene1 = nil } 

And I call this method from my GameScene as follows:

 self.viewController.nextSceneAction(self) 

I copied yours exactly, but I get the error unexpectedly found nil while unwrapping an Optional value in the line commented above. Deinit does not call.

+5
source share
1 answer

In my project, I used the following mechanism, and it worked well. All of my SKScene objects were optional. When I need a new scene to show, I create it and present it in SKView . When I need to display a new scene, I set the previous scene object of the nil object, this immediately reduces the number of links by 1, and since at that moment no object is using my scene, the reference count becomes zero and the scene has been deleted.

SKScene object is an ordinary class object, and ARC works with them as with all objects of a reference type. You only need to monitor the number of links to the scene. It all ended up with various resources that I started in the deinit a SKScene object

A simple example:

In the UIViewController we have optional GameScene objects:

 class GameViewController: UIViewController { var scene1: GameScene? var scene2: GameScene? var skView: SKView? // Action to present next Scene @IBAction func nextSceneAction(sender: AnyObject) { print("Next scene") // Create new GameScene object scene2 = GameScene(fileNamed:"GameScene") // Present scene2 object that replace the scene1 object skView!.presentScene(scene2) scene = nil } override func viewDidLoad() { super.viewDidLoad() // Create GameScene object scene = GameScene(fileNamed:"GameScene") skView = (self.view as! SKView) skView!.showsFPS = true skView!.showsNodeCount = true skView!.ignoresSiblingOrder = true scene!.scaleMode = .AspectFill // Present current scene skView!.presentScene(scene) } } 

In GameScene in deinit type some text to indicate that the object will be deleted:

 class GameScene: SKScene { ... deinit { print("Deinit scene") } } 

Debug output after clicking nextSceneAction button:

Next scene

Deinit Scene

0
source

Source: https://habr.com/ru/post/1234923/


All Articles