Save generated Scene causes duplicates

Godot Version

4.2

Question

Hi,

I’ve been trying to create a plug-in to generate a sequence of events. It’s basically a list of components and I’ve been trying to save those as a Scene using the ResourceSaver.

func save(filename, events):
	set_ownership(events, events)
	var scene = PackedScene.new()
	scene.pack(events)
    ResourceSaver.save(scene, filename)

Set ownership is basically just a function that goes through all the children and sets the owner to the root node.

func set_ownership(p_owner, node) -> void:
	for child in node.get_children():
		child.owner = p_owner
		set_ownership(p_owner, child)

That works just fine, if I run it as program. When I try to use it as a plug-in though, godot complains: “An incoming node’s name clashes with node already in the scene”.

I’ve tracked the error down and as far as I understand the problem is the following. I have a component as .tscn file like the following:

[gd_scene load_steps=3 format=3 uid=“uid://b802p7ooivsc6”]

[ext_resource type=“StyleBox” uid=“uid://l8xwosy4x2pu” path=“res://addons/test/style_box_normal.tres” id=“1_v2r0y”]
[ext_resource type=“Script” path=“res://addons/test/event_component.gd” id=“2_hwova”]

[node name=“EventComponent” type=“PanelContainer”]
custom_minimum_size = Vector2(0, 80)
anchors_preset = 10
anchor_right = 1.0
offset_left = -2.0
offset_right = -2.0
grow_horizontal = 2
focus_mode = 1
theme_override_styles/panel = ExtResource(“1_v2r0y”)
script = ExtResource(“2_hwova”)

[node name=“HFlowContainer” type=“HFlowContainer” parent=“.”]
layout_mode = 2

When I press a button, a component like this is added to a VBoxContainer. Eventually I save the VBoxContainer, all the childrens “owners” are changed to the VBoxContainer and the scene gets saved.

[gd_scene load_steps=4 format=3]

[ext_resource type=“PackedScene” path=“res://addons/test/event_component.tscn” id=“1_ke0rr”]
[ext_resource type=“StyleBox” path=“res://addons/test/style_box_normal.tres” id=“2_hkqbs”]
[ext_resource type=“Script” path=“res://addons/test/event_component.gd” id=“3_vkc4l”]

[node name=“@VBoxContainer@10” type=“VBoxContainer”]
layout_mode = 2
size_flags_horizontal = 3

[node name=“EventComponent” type=“PanelContainer” parent=“.” instance=ExtResource(“1_ke0rr”)]
custom_minimum_size = Vector2(0, 80)
layout_mode = 2
focus_mode = 1
theme_override_styles/panel = ExtResource(“2_hkqbs”)
script = ExtResource(“3_vkc4l”)

[node name=“HFlowContainer” type=“HFlowContainer” parent=“EventComponent”]
layout_mode = 2

As you can see here the file that I saved has an “ExtResource” to the original scene plus the node “HFlowContainer”. I assume that the node “HFlowContainer” is also present in the reference to the PackedScene and will then cause a clash of node names.

I’ve tried removing the “instance=ExtResource(…)” by hand and then it works again, but I don’t know how to save programatically created scenes correctly to prevent it from happenening.

What am I doing wrong?

You can have a parent and child with the same name, but you can’t have siblings of the same name.

I tried to understand what you are pointing at but none of this seems related to sibling name conflicts.

When this happens Godot may try to rename the node with some numbers to make it unique. If it’s just a warning is it possible to see the remote tree, or print the tree, after the name collision warning?

2 Likes

Well I think what happens is:

The PackedScene
[ext_resource type=“PackedScene” path=“res://addons/test/event_component.tscn” id=“1_ke0rr”]
contains a node called “HFlowContainer”.

The Scene that I save contains a reference to the scene
[node name=“EventComponent” type=“PanelContainer” parent=“.” instance=ExtResource(“1_ke0rr”)]
plus the explicit node
[node name=“HFlowContainer” type=“HFlowContainer” parent=“EventComponent”] --.

… and these two HFlowContainer nodes somehow clash with eachother.

Now I’ll be honest with you. I don’t know how these Godot formats work, but as I said already: When I remove the PackedScene line and the “instance=…” reference the error does not occur.

I think it’s also important to note that it only happens when used as a plugin. I don’t know if the @tool annotation plays a role. As far as I can tell the error happens, when saving/loading the file.

I was trying to avoid building a minimal example, but I can try if need be.

Ah okay,

So it’s
Scene root

    • Packed scene < has hflow >
      • child hflow

If this is the case yeah it looks like your trying to stuff a child with the same name into a scene that has one already.

Just rename one of them.

1 Like

But why is it duplicated in the first place?

Like this is what I am doing:

I have a plugin with some buttons. Everytime I press the button the PackedScene is loaded and added to a VBoxContainer. I then try to save the VBoxContainer.

Why is hflow present twice? I only want it once. The VBoxContainer only contains the child once. Only after saving is the element present twice with the

  • Packed scenen < has hflow >
  • child hflow

My SceneTree during runtime is:

  • VBox
  • Panel
  • hflow

no duplicates. Like the ResourceSaver somehow adds it twice. Maybe I need to build a minimal example.

This is the packed scene above

Your hflow says its a child of the packed scene that contains its own hflow.

Scene root foo
 - event component
    - internal event component hflow
    - foo hflow

The packed scene will be unrolled and the foo hflow will be its child too.

1 Like

Yes. But what I want is:

I have a Scene somewhere. I press a button and that Scene gets added to a
VBoxContainer.

I then have a list of scenes and I want to save it as a new Scene. The ResourceSaver will save a reference to the PackedScene and because I change the owner of all the child nodes (I guess) it will also save the nodes explicitly.

I assume that’s how it happens.

But if I don’t change the owner, then I can’t save my new Scene or it only saves 1 level deep. How can I save it without the duplicates?

Thanks for the discussion. I think I found it, but it does feel like a hack. The more I think about the more I think I shouldn’t use Godots ResourceSaver.

Anyways… I can just set:

node.scene_file_path = “”

to be an empty String for all the children. This will prevent the reference to the PackedScene and save it as basically a new scene and the child nodes still have their references to the scripts.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.