Duplicate orphan created when loading packedscene with dictionary/arrays storing node references
Tested versions
tested in: v4.2.stable.official [46dc27791]
System information
Godot v4.2.stable - Windows 10.0.22631 - GLES3 (Compatibility) - Intel(R) Iris(R) Plus Graphics (Intel Corporation; 27.20.100.9664) - Intel(R) Core(TM) i7-1065G7 CPU @ 1.30GHz (8 Threads)
Issue description
When saving and loading with PackedScene, it is possible to preserve node reference in the form of variables, but attempting to do the same with node references stored in a Dictionary or Array results in unusual behavior:
- when the packed scene is loaded, the referenced node will be created and placed as expected
- however, references in dictionaries and arrays will not point to that node
- the references point instead to duplicates of that node which are orphans
Code of the node storing the references:
extends Sprite2D
@export var my_gamma : Node2D
@export var my_gamma_dict : Dictionary = {0 : null}
@export var my_gamma_array : Array = [null]
func _on_button_print_gamma_pressed():
#var g = my_gamma as Node2D ## this will correctly associate my_gamma with the loaded gamma node
#var g = my_gamma_dict[0] as Node2D ## this creates an orphaned gamma and another gamma visible in game
var g = my_gamma_array[0] as Node2D ## same as above
g.visible = not g.visible
print("g.get_path() = ", g.get_path())
Steps to reproduce
Open minimal project, run:
- click the button "spawn"
- press "save"
- close and reopen the game
- press "load".
After this, duplicate orphans would have been created.
You can check the path of the "gamma" objects by pressing on the "print gamma" buttons. You can also modify the code in alpha.gd and beta.gd to try storing references to gamma in other ways
Minimal reproduction project (MRP)
Opened related discussion: https://github.com/godotengine/godot-proposals/discussions/9275
Just ran into this one and it's causing some big pains. Was very confusing to try and figure out why my objects weren't appearing in the scene.
Update as for v4.3.stable.official [77dcf97d8]:
the issue has been fixed for arrays containing node reference, but has not been fixed for dictionaries.
that is to say:
@export var _array_nodes : Array # this will work as expected without dysfunctional behavior
@export var _dict_nodes_to_values : Dictionary # this will not work as expected regardless of whether the node is the key or value
this is what the save file looks like with a single Label that I'm trying to save (added empty lines to separate the variables):
_added_labels = [NodePath("@Label@316")]
_dict_labels_to_values = {
Object(Label,"_import_path":NodePath(""),"unique_name_in_owner":false,"process_mode":0,"process_priority":0,"process_physics_priority":0,"process_thread_group":0,"physics_interpolation_mode":2,"auto_translate_mode":0,"editor_description":"","visible":true,"modulate":Color(1, 1, 0, 1),"self_modulate":Color(1, 1, 1, 1),"show_behind_parent":false,"top_level":false,"clip_children":0,"light_mask":1,"visibility_layer":1,"z_index":0,"z_as_relative":true,"y_sort_enabled":false,"texture_filter":0,"texture_repeat":0,"material":null,"use_parent_material":false,"clip_contents":false,"custom_minimum_size":Vector2(0, 0),"layout_direction":0,"layout_mode":2,"size_flags_horizontal":1,"size_flags_vertical":4,"size_flags_stretch_ratio":1.0,"localize_numeral_system":true,"tooltip_text":"","focus_neighbor_left":NodePath(""),"focus_neighbor_top":NodePath(""),"focus_neighbor_right":NodePath(""),"focus_neighbor_bottom":NodePath(""),"focus_next":NodePath(""),"focus_previous":NodePath(""),"focus_mode":0,"mouse_filter":2,"mouse_force_pass_scroll_events":true,"mouse_default_cursor_shape":0,"shortcut_context":null,"theme":null,"theme_type_variation":&"","text":"label","label_settings":null,"horizontal_alignment":0,"vertical_alignment":0,"autowrap_mode":0,"justification_flags":163,"clip_text":false,"text_overrun_behavior":0,"ellipsis_char":"…","uppercase":false,"tab_stops":PackedFloat32Array(),"lines_skipped":0,"max_lines_visible":-1,"visible_characters":-1,"visible_characters_behavior":0,"visible_ratio":1.0,"text_direction":0,"language":"","structured_text_bidi_override":0,"structured_text_bidi_override_options":[],"script":null)
: true
}
_dict_values_to_labels = {
1: Object(Label,"_import_path":NodePath(""),"unique_name_in_owner":false,"process_mode":0,"process_priority":0,"process_physics_priority":0,"process_thread_group":0,"physics_interpolation_mode":2,"auto_translate_mode":0,"editor_description":"","visible":true,"modulate":Color(1, 1, 0, 1),"self_modulate":Color(1, 1, 1, 1),"show_behind_parent":false,"top_level":false,"clip_children":0,"light_mask":1,"visibility_layer":1,"z_index":0,"z_as_relative":true,"y_sort_enabled":false,"texture_filter":0,"texture_repeat":0,"material":null,"use_parent_material":false,"clip_contents":false,"custom_minimum_size":Vector2(0, 0),"layout_direction":0,"layout_mode":2,"size_flags_horizontal":1,"size_flags_vertical":4,"size_flags_stretch_ratio":1.0,"localize_numeral_system":true,"tooltip_text":"","focus_neighbor_left":NodePath(""),"focus_neighbor_top":NodePath(""),"focus_neighbor_right":NodePath(""),"focus_neighbor_bottom":NodePath(""),"focus_next":NodePath(""),"focus_previous":NodePath(""),"focus_mode":0,"mouse_filter":2,"mouse_force_pass_scroll_events":true,"mouse_default_cursor_shape":0,"shortcut_context":null,"theme":null,"theme_type_variation":&"","text":"label","label_settings":null,"horizontal_alignment":0,"vertical_alignment":0,"autowrap_mode":0,"justification_flags":163,"clip_text":false,"text_overrun_behavior":0,"ellipsis_char":"…","uppercase":false,"tab_stops":PackedFloat32Array(),"lines_skipped":0,"max_lines_visible":-1,"visible_characters":-1,"visible_characters_behavior":0,"visible_ratio":1.0,"text_direction":0,"language":"","structured_text_bidi_override":0,"structured_text_bidi_override_options":[],"script":null)