How to Pack Subnodes of the Root node being packed

Godot Version

4.4.1

Question

Hello, So i have been trying to create a save/load system, and have everything working now besides one thing. I have a base building system that creates objects dynamically and adds them as children to the root node

Homebase>Tent(this is the dynamic built item)

and this is the code that works setting the owner: get_node(“/root/Node2D/HomeBase”).add_child(building_instance)
building_instance.owner = get_node(“/root/Node2D/HomeBase”)

These items correctly save and load, but when an item is put in the interior of a building it changes to /root/Node2D/Homebase/BUILDING/Interior/ITEM

building_instance.get_parent().remove_child(building_instance)
Global.interior.add_child(building_instance)
building_instance.set_owner(Global.interior.get_owner())

i have also tried :
building_instance.owner = get_node(“/root/Node2D/HomeBase”)

And pretty much all other combinations of setting the owner, So really not sure how pack works it seems it only packs direct children of the root being packed, so how could i save these subnodes as well?

Summary:

Children of Root (Homebase) being packed are saved and loaded, but subnodes are not. When reloaded all items are present except any item inside the building interiors.

Every node you add needs to have the same Node.owner node. If, for example, /root/Node2D/Homebase/BUILDING/Interior does not have the owner pointing to the node you want to be the root of your scene then children of that node won’t be in the scene even if their owner property point to the correct node.

So, make sure that every node you add to the node you want to be the root node of your scene has correctly set the owner property pointing to that node. Also, make sure that you do that after adding the node and not before.

If you want to be sure everything is setup correctly then you can use Node.propagate_call() to set the owner in all the nodes.

Example:

extends Node


func _ready() -> void:
	var root = Node.new()
	root.name = "root"
	add_child(root)
	for i in 10:
		add(Node.new(), root)

	root.propagate_call("set_owner", [root])

	var ps = PackedScene.new()
	ps.pack(root)
	ResourceSaver.save(ps, "res://test_owner_propagate_call_scene.tscn")


func add(node:Node, parent:Node) -> void:
	parent.add_child(node)
	if randi() % 2 == 0:
		for i in randi_range(1, 3):
			add(Node.new(), node)

(The debugger will show an error as propagate_call() also calls that function in the root node which is not correct but you can omit that, it won’t cause any issues)

Result: