0 votes

I've tried every thing I've seen on google related to the issue I'm having, but there's either a version difference, magic gnomes in my computer, or I'm making some stupid mistake.

This is how my code looks like:

var weaponTest = weaponList[2].duplicate()
weaponList[2].description = "test" <- this line is just to check if I'm not by some getting a reference by some magical way
print(weaponTest.description)

weaponList is just some list which has empty nodes with scripts attached to it, each having some variables about the weapon. When trying to dupe the node into some other variable, the result is that the node has the script attached, but no variables get copied over (just null gets returned).

I've no idea why this doesn't work, as this reddit thread shows it working beautifully.

Godot version 3.2.3.stable
in Engine by (31 points)

1 Answer

+2 votes
Best answer

3 things:
First, you're changing a value in the original node, weaponList[2]and expecting that change to be reflected in the duplicated node, weaponTest. That doesn't work. They're separate nodes, not linked. Changes to the original will not affect the duplicate.

Second, when a node is duplicated, all its properties will be assigned its default values, not the current values of the original node.

Third, in the thread you linked to, in the first answer by willnationsdev, no values are copied to the duplicate. The duplicated node just assigns its default values when created.

To do what you want (actually copy values to the duplicated node), you can create a function for that.

I have a scene called Obj.tscn, with an Obj.gd script:

# Obj.gd
extends Node

class_name Obj

var health = 0
var energy = 0
var offense = 0
var defense = 0

I also have a Main.tscn with a Main.gd script:

# Main.gd
extends Node

const PACKED_OBJ := preload("res://Scenes/Obj/Obj.tscn")

func get_copy(source_node: Node) -> Node: # will copy script var values
    assert(source_node)
    var duplicate_node = source_node.duplicate()

    var script_property_dict := get_script_property_dict(source_node)
    var var_names := script_property_dict.keys()
    var var_values := script_property_dict.values()
    for i in var_names.size():
        var var_name: String = var_names[i]
        var var_value = var_values[i]
        duplicate_node.set(var_name, var_value)

    return duplicate_node

func get_script_property_dict(node: Node) -> Dictionary:
    assert(node)
    var node_script: Script = node.get_script()
    assert(node_script)
    var script_property_dict := {}
    var script_property_list: Array = node_script.get_script_property_list()

    for i in script_property_list.size():
        var property_dict: Dictionary = script_property_list[i]
        var property_name: String = property_dict["name"]
        var property_value = node.get(property_name)
        script_property_dict[property_name] = property_value

    return script_property_dict

func print_script_vars(node: Node) -> void:
    assert(node)
    var script_property_dict := get_script_property_dict(node)
    var keys := script_property_dict.keys()
    var values := script_property_dict.values()
    for i in script_property_dict.size():
        print(keys[i], ": ", values[i])


func _ready():
    var obj: Obj = PACKED_OBJ.instance()

    obj.health = 100
    obj.energy = 50
    obj.offense = 10
    obj.defense = 7

    var obj_copy: Obj = get_copy(obj)

    print(" ----- source node -----")
    print_script_vars(obj)
    print(" ----- duplicate node -----")
    print_script_vars(obj_copy)

When running the Main scene, you'll get this output:

 ----- source node -----
health: 100
energy: 50
offense: 10
defense: 7
 ----- duplicate node -----
health: 100
energy: 50
offense: 10
defense: 7
by (236 points)
selected by

Yeah, that's what I eventually figured out I had to do. It's unfortunate there isn't some way to just copy the current variables, because the copy function I had to write had ~120 lines just because of the number of variables. I remember there being something like this in Unity, disappointing it isn't a thing in Godot.

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read Frequently asked questions and How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to [email protected] with your username.