How do I change scenes in SceneKit?

Let's say I have game levels:

level_1.scn
,
level_2.scn
,
level_3.scn
and so on. What's the best way to go from the current level to the next level if the player has completed the level?


Here's what I tried:

extension GameViewController: SCNPhysicsContactDelegate {

    func physicsWorld(_ world: SCNPhysicsWorld, didEnd contact: SCNPhysicsContact) {
        guard let nodeA = contact.nodeA.name else { return }
        guard let nodeB = contact.nodeB.name else { return }

        if nodeA == "player" && nodeB == "finishLine" || nodeA == "finishLine" && nodeB == "player" {
            if let scene = SCNScene(named: "scenes.scnassets/level_2.scn") {
                sceneView.present(scene, with: .fade(withDuration: 0.25), incomingPointOfView: nil, completionHandler: nil)
            }
        }
    }
}


Once this part of the code is executed, the scene is changed, but with a significant delay. My levels are pretty simple and I don't think they should be loaded for more than 1 second. And after the scene changes, I lose the ability to control the player.


Looks like I'm doing something wrong. Because the console displays a warning: Scene is modified within a rendering callback of another scene (). This is not allowed and may lead to a crash.


How to create the correct logic for changing scenes?

Replies

not sure why your scene is taking long to present but that's the way to do it. you could reference your scene before you need to load it and prepare it for presentation. then when you get to present it, it will already be loaded.


also you might be losing control of your player because it doesn't exists in the new "level_2.scn". nodeA and nodeB refer to a nodes in the current scene and they mean nothing when the new scene is loaded. you need to find the nodes in the new scene or load them into the new scene somehow.