Before reading this, it might be helpful to see this article:
And also, this is my project where I found some parts to suggest feedback.
Suggestion
Although a single developer can solve the problem that I will indicate, it is better to make an option for a developer to clean up event handlers when a scene changes. Currently, it seems the event handlers in an old hierarchy remain even though the app destroys the root entity.Explanation
I'm currently developing a game that contains multiple scenes and may have a loop around those scenes in the next version.
The scenario of âMound Simulatorâ consists of three phases:
A player, who enters the game, will face a Menu scene firstly. Then, when the player clicks a âLetâs Playâ button, the scene called âMainâ will start and initiate every script in entities. When a player completes an inning (since it is a baseball game), a Result page will appear and suggest two options: Returning to the Menu scene or playing another Main scene.
The entities in a hierarchy have successfully remove when I use the following script module.
const ChangeScene = pc.createScript('changeScene');
ChangeScene.attributes.add("sceneName", {type: "string", default: "", title: "Scene Name to Load"});
ChangeScene.prototype.initialize = function() {
this.entity.on("load:scene", this.loadScene, this);
};
ChangeScene.prototype.loadScene = function () {
// Get a reference to the scene's root object
let oldHierarchy = this.app.root.findByName('Root');
// Get the path to the scene
let scene = this.app.scenes.find(this.sceneName);
// Load the scenes entity hierarchy
this.app.scenes.loadScene(scene.url, function (err, scene) {
if (!err) {
oldHierarchy.destroy();
pc.ComponentSystem.initialize(scene.root);
pc.ComponentSystem.postInitialize(scene.root);
} else {
console.error(err);
}
});
};
However, some event handlers in other entities and script modules remain and stay open. Due to the leftovers, the new scene still reacts to the entities in the previous scene, even though it disappears.
For example, the following screenshot shows the error after a player enters the Main scene, returns to the Menu, and opens Settings UI. (In addition, the Main scene also has identical Settings UI entity with a few more functions and event handlers)
// initialize code called once per entity
PitcherUI.prototype.initialize = function() {
this.app.inningMaster.on('pitch', this.onPitch, this);
this.app.inningMaster.on('conclude', (ball) => this.showUmpireText(ball), this);
this.app.inningMaster.on("reset", this.reset, this);
this.app.on("change:settings", this.onChangeSettings, this);
};
PitcherUI.prototype.postInitialize = function() {
this.onChangeSettings();
};
PitcherUI.prototype.onChangeSettings = function() {
switch (parseInt(this.app.settings.pitchTraceDisplay)) {
case 0:
this.entity.script.arrowUI.fire("enable:inputUI", true);
this.entity.script.mouseHistoryUI.fire("enable:inputUI", false);
break;
case 1:
this.entity.script.arrowUI.fire("enable:inputUI", false);
this.entity.script.mouseHistoryUI.fire("enable:inputUI", true);
break;
}
};
The newly implanted event handler on âchange:settingsâ in the Main Scene stays active while âthis.entity.script.arrowUIâ no longer exists. Therefore the game throws such an error.
So I add additional lines in the module ChangeScene:
ChangeScene.prototype.loadScene = function () {
// Get a reference to the scene's root object
let oldHierarchy = this.app.root.findByName('Root');
// Get the path to the scene
let scene = this.app.scenes.find(this.sceneName);
// New Lines
this.app.off();
if (this.app.mouse) this.app.mouse.off();
if (this.app.touch) this.app.touch.off();
// Load the scenes entity hierarchy
this.app.scenes.loadScene(scene.url, function (err, scene) {
if (!err) {
oldHierarchy.destroy();
pc.ComponentSystem.initialize(scene.root);
pc.ComponentSystem.postInitialize(scene.root);
} else {
console.error(err);
}
});
};
And now, the application refreshes the obsolete event handlers every time a scene changes. Those old event handlers may re-initialize on each scene initialization while not unnecessarily duplicating itself.
Is it better to purge any event handler in the destroyed entity? I actually have no clue on the deeper part of the Playcanvas engine, so this question is not that rhetorical. Anyway and anyhow, a developer have to turn off the event handlers while loading another scene. Aside of my suggestion, is there any other elaborate method to manage the event handlers?