I'm new to Godot and also having a similar, strange problem.
I have a simple scene. I have a ball.tsvn object with a script attached, and when I click, it creates another ball once.
The "Original" ball shows the @export as "PackedScene" with a resource path like res://Scene.tscn::PackedScene_ddo6q
The first copy shows the @export as an icon with the resource path res://Prefabs/ball.tscn
The copy of the first copy shows the shows the export path as null

I've tried using the "Local to Scene" ticked and unticked to no avail.
Here is the relevant code:

@export var ball_to_spawn: PackedScene
var create: bool = true

func _spawn():
	if create:	
		create = false
		var new_ball = ball_to_spawn.instantiate();
		get_parent().add_child(new_ball)
		new_ball.global_position = global_position
  • xyz replied to this.

    xyz Oh dang. How do you get around this? I'm coming from Unity and was seeing @export as the equivalent of [SerializeField] which would let you to set the reference to a "prefab" from which you would make copies of and it wouldn't matter if it was referencing itself.
    scene/resources/resource_format_text.cpp:1861 - Circular reference to resource being saved found: 'res://Prefabs/ball.tscn' will be null next time it's loaded.

      troutmonkey Is this Godot 3? I think I only ever had one circular reference issue with 4 but I think it was fairly common in 3.

      Edit: Oh nevermind, you use @export so it has to be Godot 4.

      • xyz replied to this.

        Toxe Is this Godot 3? I think I only ever had one circular reference issue with 4 but I think it was fairly common in 3.

        4.x will complain as well.

        Not sure why the first copy would behave differently but it is expected that ball_to_spawn would be null on new instances because there's no default value assigned. If you want the copies to inherit that value you'd need to copy it explicitly:
        new_ball.ball_to_spawn = ball_to_spawn

        Or if you're always going to be instantiating the same scene, you could instead just change that first line to:
        var ball_to_spawn: PackedScene = preload("res://Prefabs/ball.tscn")

          soundgnome The problem is that the scene resource references itself. This causes an infinite reference cycle. It causes trouble when de/serializing and is in general a sign of problematic project architecture that needs to be rethinked/refactored. As OP already determined, the engine complains about it and in the error message explicitly states that it will nullify that reference. It's done in order to break the cycle.

            5 days later

            soundgnome When I used the preload method, the other scripts on the "ball" wouldn't work for some reason. The ball had two methods - jump(), and spawn(). If I used the preload it would work but then the jump functionality did not work on any of the created balls.
            I'm still learning the differences and don't quite understand the differences between the preload, @export and the various options and why they behave differently

            xyz I wanted the ball to point to the version of itself on disk, and for instances of the ball to always point to the disk version to create instances from. This is something other engines do natively so I was surprised it would break here. This was just a demo project to learn Godot so I guess I've found a limitation, but it does feel odd to have to use a second object to keep the reference on...

            • xyz replied to this.

              troutmonkey I wanted the ball to point to the version of itself on disk

              Why?