• 2D
  • How to get copy of an object?

Hello. When I was need to get duplicate of object I noticed that for some reason this is a problem. I tried use inst2dict built-in function, but it works with nodes only, while I need copy of AStar2D. Yes, I can create new instance and manually fill it using getters of other object (get_points, for example), but this will work slowly and the code of this will seem terrible.

Maybe, community has some experience solving this? Of course, using GDScript.

19 days later

@Perodactyl duplicate only inside Resource class, Object and Reference has no methods to duplicate. Astar2D inherits Reference.

I don’t think there is anything for duplicating an Object built-in to Godot, unfortunately. You might be able to make your own duplication code using get_property_list and the get and set functions, but it might be slow. Something like this could, in theory, work:

# object_1 is the object we want to copy

var object_2 = object_1_class.new()
for property in object_1.get_property_list():
	object_2.set(property[“name”], object_1.get(property[“name”])

I don’t know if it would work though.

@TwistedTwigleg as I know, get_property_list functions doesn't works with built-in variables, so you can't edit them directly whatever you do.

You could probably use get_property_list() and work from there, unless you need methods, in which case good luck.

# Output is probably just making another instance of the object.
func duplicate(object:Object, output:Object):
	for property in object.call("_get_property_list"):
		output[property.name] = object.get(property.name)

It doesn't return a value, it just copies over properties, which won't work from what I've heard of Astar2D.<br>It also isn't tested.

@TTaykAH said: @TwistedTwigleg as I know, get_property_list functions doesn't works with built-in variables, so you can't edit them directly whatever you do.

Oh, that might be the case. If so, then yeah, using the property list won't work then. I'll keep thinking about other possible solutions and will post if I think of anything.

I tried use Array with its duplicate method which has deep as parameter. So, It hadn't worked. Now, I don't quite understand what this argument does. By the way, I have been testing with this code:

func _ready():
	var astar = AStar2D.new() # object to duplicate
	
	var t = [astar] # creating array with it
	var g = t.duplicate(true) # "duplicating"
	
	g[0].add_point(6, Vector2(1, 1)) # changing new object
	
	print(astar.get_points()) # Definitely, astar hadn't changed. No.

Regretfully, output isn't an empty array.

a month later

@TTaykAH said: I tried use Array with its duplicate method which has deep as parameter. So, It hadn't worked. Now, I don't quite understand what this argument does. By the way, I have been testing with this code:

func _ready():
	var astar = AStar2D.new() # object to duplicate
	
	var t = [astar] # creating array with it
	var g = t.duplicate(true) # "duplicating"
	
	g[0].add_point(6, Vector2(1, 1)) # changing new object
	
	print(astar.get_points()) # Definitely, astar hadn't changed. No.

Regretfully, output isn't an empty array.

Deep set to true means duplicate without sharing anything. Setting it to false should be the equivalent to having a reference to the original array. Sorry if this isn't useful for the current problem, just wanted to at least explain the deep parameter a little :)

In any case, I am wishing you the absolute best and a wonderful day!

5 months later

Why don't you prebuild the object or what ever as a class then instance it and set the variables then or pull them from an exsisting object

Yes. For this you want to make your own Scene object. You can inherit from any included class and choose to add additional functionality or not. Then use load or preload on ready (or onready) to load your scene file. Then in your code use the instance() function to make a copy.

@Rukus @cybereality I meant duplicating Reference. To get copy of node you can use inst2dict and inverse function. Creating new reference you can't change built-in fields, so it could be done with getters and setters, which slow and matches only one type. If I will write duplicate method for Astar, I can't use it with SurfaceTool etc.

    2 years later

    TTaykAH I am stuck on the exact same problem! I am not very versed in GDScript yet but for Godot 4 I do make my custom duplicate method, it still depend on what type of class like if it contains sub resources then this will not work!

    class_name MyClass
    var some_float: float
    var some_bool: bool
    
    func duplicate(class_object: MyClass) -> void:
    	some_bool = class_object.some_bool
    	some_float = class_object.some_float

    Again, this implementation only works for simple classes I am still unable to handle it if class have some resource type as member for example "InputEvent" :

    • xyz replied to this.

      xyz Wow, my brain has completely malfunctioned in these couple of days I guess 😐 But thank you for the idea!
      Updated code!

      class_name MyClass
      var some_float: float
      var some_bool: bool
      var some_resouce: Resource
      
      func duplicate(class_object: MyClass) -> void:
      	some_bool = class_object.some_bool
      	some_float = class_object.some_float
      	some_resource = class_object.some_resource.duplicate(true) # pass true if your resource also contains sub resources!