@@ -586,7 +586,7 @@ bool SceneTree::process(double p_time) {
586586 MessageQueue::get_singleton ()->flush (); // small little hack
587587 flush_transform_notifications (); // transforms after world update, to avoid unnecessary enter/exit notifications
588588
589- if (unlikely (pending_new_scene )) {
589+ if (unlikely (pending_new_scene_id. is_valid () )) {
590590 _flush_scene_change ();
591591 }
592592
@@ -1508,17 +1508,33 @@ Node *SceneTree::get_current_scene() const {
15081508}
15091509
15101510void SceneTree::_flush_scene_change () {
1511- if (prev_scene) {
1512- memdelete (prev_scene);
1513- prev_scene = nullptr ;
1511+ if (prev_scene_id.is_valid ()) {
1512+ // Might have already been freed externally.
1513+ Node *prev_scene = Object::cast_to<Node>(ObjectDB::get_instance (prev_scene_id));
1514+ if (prev_scene) {
1515+ memdelete (prev_scene);
1516+ }
1517+ prev_scene_id = ObjectID ();
15141518 }
1515- current_scene = pending_new_scene;
1516- root->add_child (pending_new_scene);
1517- pending_new_scene = nullptr ;
1518- // Update display for cursor instantly.
1519- root->update_mouse_cursor_state ();
15201519
1521- emit_signal (SNAME (" scene_changed" ));
1520+ DEV_ASSERT (pending_new_scene_id.is_valid ());
1521+ Node *pending_new_scene = Object::cast_to<Node>(ObjectDB::get_instance (pending_new_scene_id));
1522+ if (pending_new_scene) {
1523+ // Ensure correct state before `add_child` (might enqueue subsequent scene change).
1524+ current_scene = pending_new_scene;
1525+ pending_new_scene_id = ObjectID ();
1526+
1527+ root->add_child (pending_new_scene);
1528+ // Update display for cursor instantly.
1529+ root->update_mouse_cursor_state ();
1530+
1531+ // Only on successful scene change.
1532+ emit_signal (SNAME (" scene_changed" ));
1533+ } else {
1534+ current_scene = nullptr ;
1535+ pending_new_scene_id = ObjectID ();
1536+ ERR_PRINT (" Scene instance has been freed before becoming the current scene. No current scene is set." );
1537+ }
15221538}
15231539
15241540Error SceneTree::change_scene_to_file (const String &p_path) {
@@ -1538,21 +1554,23 @@ Error SceneTree::change_scene_to_packed(const Ref<PackedScene> &p_scene) {
15381554 ERR_FAIL_NULL_V (new_scene, ERR_CANT_CREATE);
15391555
15401556 // If called again while a change is pending.
1541- if (pending_new_scene) {
1542- queue_delete (pending_new_scene);
1543- pending_new_scene = nullptr ;
1557+ if (pending_new_scene_id.is_valid ()) {
1558+ Node *pending_new_scene = Object::cast_to<Node>(ObjectDB::get_instance (pending_new_scene_id));
1559+ if (pending_new_scene) {
1560+ queue_delete (pending_new_scene);
1561+ }
1562+ pending_new_scene_id = ObjectID ();
15441563 }
15451564
1546- prev_scene = current_scene;
1547-
15481565 if (current_scene) {
1566+ prev_scene_id = current_scene->get_instance_id ();
15491567 // Let as many side effects as possible happen or be queued now,
15501568 // so they are run before the scene is actually deleted.
15511569 root->remove_child (current_scene);
15521570 }
15531571 DEV_ASSERT (!current_scene);
15541572
1555- pending_new_scene = new_scene;
1573+ pending_new_scene_id = new_scene-> get_instance_id () ;
15561574 return OK;
15571575}
15581576
@@ -2009,13 +2027,19 @@ SceneTree::SceneTree() {
20092027}
20102028
20112029SceneTree::~SceneTree () {
2012- if (prev_scene) {
2013- memdelete (prev_scene);
2014- prev_scene = nullptr ;
2030+ if (prev_scene_id.is_valid ()) {
2031+ Node *prev_scene = Object::cast_to<Node>(ObjectDB::get_instance (prev_scene_id));
2032+ if (prev_scene) {
2033+ memdelete (prev_scene);
2034+ }
2035+ prev_scene_id = ObjectID ();
20152036 }
2016- if (pending_new_scene) {
2017- memdelete (pending_new_scene);
2018- pending_new_scene = nullptr ;
2037+ if (pending_new_scene_id.is_valid ()) {
2038+ Node *pending_new_scene = Object::cast_to<Node>(ObjectDB::get_instance (pending_new_scene_id));
2039+ if (pending_new_scene) {
2040+ memdelete (pending_new_scene);
2041+ }
2042+ pending_new_scene_id = ObjectID ();
20192043 }
20202044 if (root) {
20212045 root->_set_tree (nullptr );
0 commit comments