Script Variable State Lost When Duplicating Node Tree in Godot 4.4.1

Godot Version

v4.4.1.stable.steam [49a5bc7b6]

Question

I’m trying to duplicate a node and its children (including scripts and variable states), but the script variable values always reset after duplication. My node structure:

main (Control, script main.gd)
└── Control (named “control”)
└── a (TextureRect, script a.gd)
└── b (Label, script b.gd)

Key Code:

main.gd :

func _on_button_pressed():
print(“main: add_count pressed!”)

var a = control.get_child(0)
var c = a.duplicate(DUPLICATE_SCRIPTS)

print("old a’s count: ",a.count_a)
print("old b’s count: ",a.get_child(0).count_b)

control.remove_child(a)
control.add_child(c)

print(“main: duplicate finished!”)
print("new a’s count: ",c.count_a)
print("new b’s count: ",c.get_child(0).count_b)

a.gd:

var count_a: int

func _on_button_pressed():
print(“a: add_count pressed!”)

b.text = str(int(b.text) + 1)

b.count_b += 1
count_a += 1

b.gd:

var count_b: int

Observed Behavior:

Script variables count_a and count_b reset to 0 after duplication

Tried DUPLICATE_SCRIPTS flag without success

print information:

a: add_count pressed!
a: add_count pressed!
a: add_count pressed!
main: add_count pressed!
old a’s count: 3
old b’s count: 3
main: duplicate finished!
new a’s count: 0
new b’s count: 0

Godot 4.4.1.stable.steam [49a5bc7b6]

Thats by design, you are creating another copy in code. Is there a reason why you are doing that and not through the editor? If you do it through the editor then the variable states will be preserved. (unless you make them unique)

When I started using Godot, coming from Unity, I wanted to be able to duplicate nodes just like in Unity, where I’d use Instantiate() on GameObjects. Learned the hard way that that’s definitely not the Godot way, and that you should make scenes out of the nodes you want to duplicate.

Only recently I learned how to do this per code for runtime use, so at least it’s possible to instantly create a PackedScene and instantiate it, without filling up my project with lots of small scenes.

I’m not sure why, but the structure I sent earlier isn’t working as expected, while the one below is correct.

Main (Control, script: main.gd)
= Control (named “control”)
== a (TextureRect, script: a.gd)
=== b (Label, script: b.gd)
In fact, this is a simple example—I’ve already saved its original version as a scene. And why am I doing this? Because in the game, I have many such scenes that I modify during runtime, and sometimes I need copies of them (including the modifications made during runtime). I don’t want to manually assign values to potentially modified variables, as there are simply too many and it’s quite difficult.

So I asked an AI for help and was told to use duplicate(), but during actual runtime, I found that duplicate()doesn’t work as expected.

Thank you for your reply, but creating a PackedScene and instantiating it isn’t what I need—it would only give me an unmodified original version. What I actually require is a copy that retains the changes made during runtime.

As I said, you can create the PackedScene on runtime - anytime you want.

You didn’t actually tell us why here.

The code you posted is TBH unclear code. You shouldn’t be naming variables a and b. We have no idea what you’re actually trying to do because you’re either obfuscating your example, or it’s all in your head and you’re expecting us to be in there with you to understand what you’re doing.

Your responses to people’s recommendations so far demonstrate that you haven’t explained enough about what you’re doing and what you’ve tried. If you have already tried instantiating objects and that didn’t work, then that information should be in your initial post so you don’t waste people’s time trying to help you.

LLMs lie. Straight up. They will tell you to do things that won’t work with Godot. They will lie about functions existing.

This is my interpretation of what I’ve read so far:

  1. You had a goal.
  2. You decided the solution was to duplicate in-game objects.
  3. You asked AI for help.
  4. You got an incorrect answer.
  5. You decided that the duplicate() function didn’t do what you wanted.
  6. You asked for help with the code the AI wrote for you.

I would recommend you back up to step one and tell us specifically what you are trying to accomplish. Give us some context to work with. Tell us the problem you’re trying to solve - not the solution you came up with.

1 Like

That definitely is the Godot way and is pretty much the same as Unity (other than the implementation is slightly different with Scenes , but in the end its pretty much the same).

I’m confused by this statement tbh.

But if you create a copy of the scene in the editor add the desired information to the variable and save it, and then instantiate scene that you absolutely will get a copy with the variable information intact. That’s the whole point of scenes.

I’m not talking about prefabs. Only about GameObjects inside the scene.

Prefabs (Unity) = Scenes (Godot) . Whilst the implementation is slightly different they are in effect the same thing.

When I moved from Unity this confused me at first as well.

You don’t understand what I’m saying. I know what prefabs and scenes are. I’m talking about duplicating GameObjects within a scene in Unity, and doing the same in Godot, duplicating nodes within the tree. You can do that in Unity just fine, but not so in Godot.

Just so we are clear, a ‘GameObject’ is in effect just a class for both GD script & c#) .

A scene is a collection of them (and other components) , with all the preset information you want in them.

If you want to have a class with variables that have an preexisting information in them, or pass information to them (which I think is what you are trying to achieve) then look at this:

https://www.reddit.com/r/godot/comments/13pm5o5/instantiating_a_scene_with_constructor_parameters/

I come from c# world so don’t usually think about it tbh.

Well you can , you just right click on it and chose duplicate.

Please remember the context of this discussion. It’s about runtime duplication.

And if a packed scene was duplicated that had a game object inside of it, which in turn has some predefined information in it that was set via the editor then that information would be duplicated as well.

If you duplicate a class (in code) and the original doesn’t have predefined information in and create a copy of that then neither will the duplicate, thats exactly how Unity works as well. Along with every other class based programming language.

1 Like

You are right, I see what you mean now. Upon attempting to duplicate (using PackedScene or duplicate()), I noticed that all variables with @export correctly retained, whereas those without @export in their initial state.

such as:

@export var num1 = 0
var num2 = 0

and print information:
change it:

num1 = 5
num2 = 5

after copy:

num1 = 5
num2 = 0

1 Like

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