Omar Dlhz
Omar Dlhz

Reputation: 168

Spritekit- Scene transition Delay

I have a main screen which has a button, when this button is pressed it should transition immediately to another scene, but it doesn't. It actually takes a few seconds. Is there a way that I could load all the nodes in that scene beforehand? (Example: in the games load screen)

This is my code:

let pressButton = SKAction.setTexture(SKTexture(imageNamed: "playButtonP.png"))

            let buttonPressed = SKAction.waitForDuration(0.15)

            let buttonNormal = SKAction.setTexture(SKTexture(imageNamed: "playButton.png"))


            let gameTrans = SKAction.runBlock(){
                let doors = SKTransition.doorsOpenHorizontalWithDuration(0)
                let levelerScene = LevelerScene(fileNamed: "LevelerScene")
                self.view?.presentScene(levelerScene, transition: doors)
            }

        playButton.runAction(SKAction.sequence([pressButton,buttonPressed,buttonNormal,gameTrans]))

Upvotes: 4

Views: 1729

Answers (1)

ABakerSmith
ABakerSmith

Reputation: 22969

You could preload the SKTextures you're using in LevelerScene before presenting the scene. Then, once the loading has finished you would then present the scene. Here's an example from the Apple's Documentation, translated to Swift:

SKTexture.preloadTextures(arrayOfYourTextures) {
    if let scene = GameScene(fileNamed: "GameScene") {
        let skView = self.view as! SKView
        skView.presentScene(scene)
    }
}

In your case you have a couple of options:

1. Keep an array of the textures, which you need to use in LevelerScene, that you preload in GameScene:

class LevelerScene : SKScene {
    // You need to keep a strong reference to your textures to keep
    // them in memory after they've been loaded.
    let textures = [SKTexture(imageNamed: "Tex1"), SKTexture(imageNamed: "Tex1")]

    // You could now reference the texture you want using the array.

    //...
}

Now in GameScene, when the user presses the button:

if let view = self.view {
    let leveler = LevelerScene(fileNamed: "LevelerScene") 
    SKTexture.preloadTextures(leveler.textures) {
        // Done loading!
        view.presentScene(leveler)
    }
}

There's no way you can get around having to wait a little bit, but taking this approach the main thread won't get blocked and you'll be able to interact with GameScene whilst LevelerScene is loading.

You could also use this approach to make a loading SKScene for LevelerScene. GameScene would take you to the loading scene, which would load the textures and then move you to LevelerScene once it was complete.

It's important to note that because the reference to the textures is in LevelerScene, once LevelerScene is deinit-ed the textures will be removed from memory. Therefore, if you want to go back to LevelerScene you'll need to load the textures again.

2. You could use SKTexture.preloadTextures in GameViewController before any SKScenes have been presented. You'd need to keep a strong reference to these textures (perhaps in a singleton) which you could then reference in LevelerScene (or anywhere else you needed them in the app).

With this approach, because the SKTextures are stored outside of a scene, they won't be removed from memory when you transition to the next scene. This means you won't have to load the textures again if you leave and then go back to a scene. However, if you've got a lot of textures taking up a lot of memory you could run into some memory issues.

For more information see Preloading Textures Into Memory from Working with Sprites.

Hope that helps!

Upvotes: 3

Related Questions