Search code examples
swiftsprite-kitscenekitskactionskscene

SKScene becomes unresponsive while being Idle


Hello I have a SceneKit game. All the game play is in one scene and when the game is over the sprit kit overlay acts as a game over screen and when they hit play again the sprite kit labels disappear and the game resets all in the same scene.

My issuing is coming in the game over. If the user hits the replay button within a few seconds then everything goes well. But if the user sits on the game over place for over five seconds then the scene freezes. I am really confused as the app is idle when it freezes and I am receiving no errors. Also the memory and CPU usage are much lower during game over that during game play. Also that app itself is not frozen as if I click the menu button it transitions to a new view controller just fine.

With no memory leaks or errors I really have no idea where to begin looking for whats wrong? Can someone point me in the right direction

A little more insight to whats going on: The game is a short half minute action game that uses the physics simulation. There is a timer set to fire every 0.01 seconds that affects the game play. When the game is over (caused by one node colliding with another) the players node is removed, a variable is set to false so that when the game timer fires nothing happens, and a bunch of label nodes are created in the sprit kit overlay that act as the game over menu.

Again everything works great if the user clicks replay within fivish seconds. Clicking replay hides all the labels, creates the players node in the starting position, and sets the timers variable back true.

Here is the code for setting up the scene

// create a new scene
scene = SCNScene()
sceneView = SCNView()
sceneView.frame = self.view.frame
sceneView.autoresizingMask = UIViewAutoresizing.allZeros
sceneView.scene = scene
sceneView.autoenablesDefaultLighting = false
sceneView.allowsCameraControl = false
sceneView.showsStatistics = false
sceneView.backgroundColor = UIColor.blackColor()
scene.physicsWorld.gravity = SCNVector3Make(0, -30, 0)
scene.physicsWorld.contactDelegate = self
self.view = sceneView
self.MarbleGeo = SCNSphere(radius: 1.3)
hud = Hud(size: self.view.frame.size, game: self)
sceneView.overlaySKScene = hud

Edit

I have located where the code is breaking down. When the again button is clicked all the labels are supposed to move or fade out or some effect along those lines. Anyways the method call to restart the game is in the completion of the last of one of those effects. Here is the code

println("Before check")
MenuLabel.runAction(moveButtonsOut, completion: { () -> Void in
    self.scoreLabel.removeFromParent()
    self.MyGame.Setup()
    self.MyGame.Restart(true, Level: self.MyGame.level)
    self.startTimer()
    println("should have called the game to begin by now")
    //self.playing = true
    //self.MyGame.addMarble()
})

The first statement is logged, but the one on the inside of the completion block is not. So I guess the my question now changes to why aren't these actions being run and completed once the game freezes?

Edit

It appears that the SKActions are being kicked from the que. While in the game over scene some labels are enlarging and shrinking over and over and some fade in and out and what not. Anyways when all this is going on the replay button works great, no errors. When all these actions freeze that is when the button no longer works because the restart methods never get called on upon completion. I tried placing the restart methods outside of completion and when they were called all the actions because unfrozen and they all rush to complete and it looks awful. So to sum up something is pausing the SKActions

Hope this helps.


Solution

  • is your SceneKit scene playing ? A scene is playing when you either have

    • scene.playing = YES
    • SCNAction instances running
    • implicit or explicit animations running

    The SpriteKit scene overlay is refreshed only when the SceneKit scene is. So if the SceneKit scene does not redisplay the actions set in the overlay might not run.

    A solution might be to set the playing property or to add actions to SceneKit objects instead of SpriteKit objects.

    This is unrelated but try to keep away from timers. SceneKit provides several game loop callbacks that will allow you to do what you want.