Tiger
Tiger

Reputation: 1

Error: Scene <SCNScene:> is modified within a rendering callback of another scene (<SCNScene: >). This is not allowed and may lead to crash

I am trying to transition from one scene to another for my swift game. I am still learning and apologize for any blatant issues with my code.

This is a 3D game with animations from Blender.

I have a GameViewController and a GameController. The game has been working so far, but I am not able to get the transition without the error message.

When I try to transition to a new scene (prompted by a "gameOver" logic), the new scene shows up, but I get this error: Error: Scene <SCNScene:> is modified within a rendering callback of another scene (<SCNScene: >). This is not allowed and may lead to crash.

Here is my code - I've edited it to show only the relevant parts but please let me know if you need more information.

I don't know if I need to be creating a new GameOverViewController and / or GameOverController somewhere, to instantiate a new renderer function for the new scene? Please let me know if you have any suggestions, I appreciate your help!


//  GameViewController.swift

import UIKit
import SceneKit
import SpriteKit


protocol GameControllerDelegate: AnyObject {
    func decreaseScore()
    func gameOver2()
}

var score = 0


class GameViewController: UIViewController, SCNPhysicsContactDelegate, GameControllerDelegate {

    var gameView: SCNView {
        return self.view as! SCNView
    }

    
    var gameController: GameController!
  
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.gameController = GameController(sceneRenderer: gameView)
        self.gameController.gameDelegate = self
        gameView.scene!.physicsWorld.contactDelegate = self
      
    }
    
    
    func gameOver2() {
        gameScene?.isPaused = true
        let transition = SKTransition.doorsOpenVertical(withDuration: 1.0)
        gameView.present(gameOverScene!, with: transition, incomingPointOfView: nil, completionHandler: {
            print("completionhandler")
        })
        
    }

        
}





//  GameController.swift


import SceneKit
import UIKit
import SpriteKit



var gameScene = SCNScene(named: "Art.scnassets/Game.scn")
var endgameScene = SCNScene(named: "Art.scnassets/GameOver.scn")


class GameController: NSObject, SCNSceneRendererDelegate {


    var scene: SCNScene
    let sceneRenderer:   SCNSceneRenderer
    var gameViewController: GameViewController!
    var gameView: GameController!
    lazy var gamePlaying = true
    weak var gameDelegate: GameControllerDelegate?

    
    init(sceneRenderer renderer: SCNSceneRenderer) {
        sceneRenderer = renderer
        scene = gameScene!
        super.init()
        sceneRenderer.delegate = self
        sceneRenderer.scene = gameScene
        
    }
    

    func renderer(_ renderer: SCNSceneRenderer, didSimulatePhysicsAtTime time: TimeInterval) {

        camera?.physicsBody?.angularVelocityFactor = SCNVector3(0, 0, 0)
        camera?.position = SCNVector3(x: -7, y: ((pwet?.presentation.position.y)! + 4), z: 60)

        if gamePlaying == true {
            if score < 0 {
                DispatchQueue.main.async {
                    self.gamePlaying = false
                    self.gameDelegate?.gameOver2()
                }
            }
    }
    
   
}

edited to respond to feedback comment:

I added a couple of print statements to see which scene is being referenced where:

when I run viewDidLoad (first scene runs), it shows this scene:

viewDidLoad - gameView.scene =  <SCNScene: 0x600003701440>

when I get to the gameOver function, it tries to pause that one:

gameOver2 = gameScene.isPaused =  Optional(<SCNScene: 0x600003701440>)

and runs this one:

completionhandler gameView.present = gameOverScene =  Optional(<SCNScene: 0x600003772dc0>)

The error message references them as such:

Error: Scene <SCNScene: 0x600003701440> is modified within a rendering callback of another scene (<SCNScene: 0x600003772dc0>). This is not allowed and may lead to crash

Upvotes: 0

Views: 50

Answers (1)

Tiger
Tiger

Reputation: 1

I was able to resolve this issue by adding a gamePlaying boolean variable and setting it to true or false depending on which scene was in use.

In my renderer function I was assigning some Physics Categories to nodes from my first scene, and when I placed that piece of code inside an if statement triggered by the gamePlaying boolean, the error went away.

So basically my renderer function now includes this if statement:

if gamePlaying is true: do the things that should only happen when the gamePlaying scene is being rendered;

if gamePlaying is false: do the other things

Upvotes: 0

Related Questions