I am currently having a problem in which when switching between scenes in my game (Assuming the scenes are not just simple overlays) is throwing an error in the console. It doesn’t actually break any of my games functionality and still seems to run fine regardless of the error. This didn’t happen before the update which I believe was around the 12th onwards.
Below is the code for the Scene Manager I am using along side a screenshot of the error. Any advice would be appreciated.
var SceneManager = pc.createScript('sceneManager');
SceneManager.Instance = null;
var Scenes = Object.freeze({
Boot:{
ID: 667430,
SceneName: 'BaseScene',
SceneType: 'Base'
},
Game:{
ID: 654507,
SceneName: 'NewBaseWithAssets',
SceneType: 'Overwrite'
},
Menu:{
ID: 667431,
SceneName: 'MenuScene',
SceneType: 'Overwrite'
},
Pause:{
ID: 667432,
SceneName: 'PauseScene',
SceneType: 'Overlay'
},
Gameover:{
ID: 668321,
SceneName: 'GameoverScene',
SceneType: 'Overlay'
},
Highscore:{
ID: 668379,
SceneName: 'HighscoreScene',
SceneType: 'Overlay'
}
});
// initialize code called once per entity
SceneManager.prototype.initialize = function() {
//Assign the singleton
SceneManager.Instance = this;
//Initialise scene variables
this.lastScene = Scenes.Boot;
this.currentScene = Scenes.Boot;
this.nextScene = Scenes.Boot;
this.sceneStack = [];
//Sets the first scene that the game enters into
this.setNextScene(Scenes.Menu);
// console.log("after Init: ", this.app.root.children);
// console.log("SceneStack after init: ", this.sceneStack);
};
// update code called every frame
SceneManager.prototype.update = function(dt) {
if(this.currentScene !== this.nextScene){
this.changeScene(this.nextScene);
}
//Debug Console
// if(this.app.keyboard.wasPressed(pc.KEY_Q)){
// console.log("current: ", this.currentScene, "\nlast: ", this.lastScene, "\nnext: ", this.nextScene);
// }
};
SceneManager.prototype.setNextScene = function(newScene){
this.nextScene = newScene;
};
SceneManager.prototype.loadSceneToRoot = function(id){
this.app.loadSceneHierarchy(id + '.json', function(err, parent)
{
if (!err)
{
this.pushSceneToStack(parent);
}
else
{
console.error(err);
}
}.bind(this));
};
SceneManager.prototype.changeScene = function(newScene){
this.lastScene = this.currentScene;
this.currentScene = this.nextScene;
//overlay the new scene and add it to the scene stack
if (newScene.SceneType == "Overlay"){
//Disable the last current enabled scene to stop updates happening in it
this.sceneStack[this.sceneStack.length - 1].enabled = false;
//Overlay the new scene atop of it and put it onto the scene stack
this.loadSceneToRoot(newScene.ID);
}
//clear all current scenes then add this one
else if (newScene.SceneType == "Overwrite"){
if(this.sceneStack.length > 0){
this.clearAllScenes();
}
this.loadSceneToRoot(newScene.ID);
}
else{
console.log("We messed up somewhere with our SceneTypes RIPPO");
}
};
SceneManager.prototype.pushSceneToStack = function(rootEntity){
this.sceneStack.push(rootEntity);
console.log("App root after push: ", this.app.root.children);
console.log("SceneStack pushed to: ", this.sceneStack);
};
SceneManager.prototype.popSceneFromStack = function(){
this.sceneStack[this.sceneStack.length - 1].destroy();
this.sceneStack.pop();
this.sceneStack[this.sceneStack.length - 1].enabled = true;
var tempScene = this.currentScene;
this.currentScene = this.lastScene;
this.nextScene = this.lastScene;
this.lastScene = tempScene;
console.log("Scene stack popped: ", this.sceneStack, "\nApp roots children", this.app.root.children);
};
SceneManager.prototype.clearAllScenes = function(){
var rootChildren = this.app.root.children;
for(var i = 0; i < rootChildren.length; i++){
if(!rootChildren[i].tags.has('dontDestroy')){
rootChildren[i].destroy();
i--;
}
}
this.sceneStack = [];
console.log("Clear all scenes debug, sceneStack: ", this.sceneStack, "\napp.root.children: ", this.app.root.children);
};
Yes, the way the scene loading is done is additive, especially when i say load the pause scene as it disables the previous scene and puts in the new pause scene. However when moving into the main game since it’s an overwrite scene it clears all scenes currently on the apps root bar my base scene which has some managers on which I keep alive with the ‘dontDestroy’ tag. The error only ever appears when adding a new scene in which I delete the previous ones AKA an overwrite, This error doesn’t appear when say transitioning back and forth between the pause scene and the game scene.
I’ll test the various engine versions to see where I can see which update broke it.
From the screen shot below as far as I can tell from the error, the array getting passed into this function which is variable a isn’t defined which is why it cant find element f. Since this has references below it to things like update, fixedupdate etc could this be some sort of callback that now has hanging references due to the old scene being deleted? I can see that theres been changes to pc.BundleRegistry but I have no idea whether I would have access to deleting the registry through my scene manager.
There has been a recent change (I thought this would be in 1.10.7 TBH) that the component system will no longer fire events for update/postUpdate etc so it might be related to that. Without being able to debug myself (can you replicate the error in a smaller public project?), I can’t really be sure.
Can you find the name of what a component system is?
Currently trying to build a small scale project replicating the problem but currently the scene manager itself isn’t provoking the problem, so its something within the scenes.
In the mean time though do you have any ideas how i would find out what a is ?
Tried putting a console log into the function that throws the error in the playcanvas stable js file but it floods my console
Okay I’ve managed to recreate the error in a smaller cut down project.
In the example below I have an empty scene bar a cone and another one with a button and a cube. The button is used to switch scenes which is predefined in an attribute in the editor which is used for navigation in my other project.
Only when switching from scene with the button in it throws the error.
Use “Q” to switch to the cone scene and “W” to switch to the cube scene.
Just using the Chrome debugger to pause on exception, I can sort of see what has happened. I think the array changes length in the middle of iteration. I can’t tell what without debugging deeper. It be something for @vaios I guess.