Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

duplicate() don't copy variables values in Resources #37222

Closed
rsousacode opened this issue Mar 22, 2020 · 12 comments
Closed

duplicate() don't copy variables values in Resources #37222

rsousacode opened this issue Mar 22, 2020 · 12 comments

Comments

@rsousacode
Copy link

rsousacode commented Mar 22, 2020

Last reproduced in Godot version: da4eb71

We use Godot C#, and we don't see a proper way to get a real duplication of the Resource like in Unity (InventoryItem clone = UnityEngine.Object.Instantiate(this) as InventoryItem). In the docs says that Resource are similar to Unity Scriptable Objects but they're not for most proper use cases. In our inventory system, our items can't have the stackable option (for example having a max of 10 items per slot - for the same item), because this.Duplicate() as InventoryItem doesn't work properly. (assuming that this one is the equivalent of the refered Unity method)

Edit: Maybe we assumed wrongly the actual bold text, since duplicate is used many times in the core of the engine, but the actual exposed thing can be misleading, and people can assume that does what the unity like func does.

I previously thought that this was related to #3393, but then we realised that it was better to create another issue.

@Calinou
Copy link
Member

Calinou commented Mar 22, 2020

Please mention the Godot version you're using in issue description. Also, please upload a minimal reproduction project to make this easier to troubleshoot 🙂

@rsousacode
Copy link
Author

rsousacode commented Mar 22, 2020

This is what happens in my project:

(itemToAdd has the parameters OK)
screen1

(After adding it to the array, all important parameters bacame null)

screen2

(Will test it again in nightly 3.2 build, and post the version in a few momments)

@rsousacode
Copy link
Author

rsousacode commented Mar 22, 2020

Unity Minimal Project: https://ufile.io/w0crj713
Godot Minimal Project: https://ufile.io/tp1svyxl

The workaround is setting the variables of the duplicated resource manually, in our case we spent hours troubleshooting this, and we came to the conclusion that we didn't even set all of the variables, our IDE should have been also more helpfull. (we have dozens and dozens of vars that affect our code). With big projects, this is a must have...

@Anutrix
Copy link
Contributor

Anutrix commented Mar 26, 2020

Isn't duplicate(subresources=false) what you are looking for?
Though there does seem to some issue regarding it(see #37162 (comment)).

@rsousacode
Copy link
Author

rsousacode commented Mar 27, 2020

@Anutrix No. It was the first things I've tried.
Edit: the actual workaround we're using (is making the "deep" copy manually)
dupl

@neikeq
Copy link
Contributor

neikeq commented Apr 2, 2020

Is this only failing for user created properties/fields or does the same apply to the native class properties?

@rsousacode
Copy link
Author

rsousacode commented Apr 2, 2020

If by native class property you mean a something that is present in the original Resource inherited class, I don't think it fails, i.e. #37222 (comment) in the first screenshot TargetInventory is assigned to Inventory.Instance (which is a Singleton, and got the correct Node always). And that one never becames null, only the 'user' ones. (But that was temporary, we never want any of our inventories to be singletons) .

If you want I can open a proposal for adding this clone/duplicate functionality. Since I noticed some time after opening this issue that duplicate is used many times in godot source, and I don't think the usage should be 'confuded' as it happenned to me.

Actually I had replaced Duplicate #37222 (comment) by new InventoryItem() right there, and still works fine (as a workaround).

@MikeSchulze
Copy link

i got same error on gdScript

extends Resource
class_name ClassA

var _foo = 10
const classA = preload("res://test/ClassA.gd")

func _ready():
	ready1()
	ready2()
	ready3()

func ready1():
	prints("preloaded class duplicate(true)")
	var original:ClassA = classA.new()
	
	var c1 = original.duplicate(true)
	prints( original, original._foo, " -> ", c1, c1._foo)
	
	original._foo = 22
	c1 = original.duplicate(true)
	prints( original, original._foo, " -> ", c1, c1._foo)	

	
func ready2():
	prints("class by name  duplicate(true)")
	var original:ClassA = ClassA.new()
	
	var c1 = original.duplicate(true)
	prints( original, original._foo, " -> ", c1, c1._foo)
	
	original._foo = 22
	c1 = original.duplicate(true)
	prints( original, original._foo, " -> ", c1, c1._foo)	


func ready3():
	prints("class by name  duplicate(false)")
	var original:ClassA = ClassA.new()
	
	var c1:ClassA = original.duplicate()
	prints( original, original._foo, " -> ", c1, c1._foo)
	
	original._foo = 22
	c1 = original.duplicate()
	prints( original, original._foo, " -> ", c1, c1._foo)	

output:

--- Debugging process started ---
Godot Engine v3.2.2.stable.mono.official - https://godotengine.org
OpenGL ES 2.0 Renderer: GeForce GTX 980/PCIe/SSE2
OpenGL ES 2.0 Batching: ON
 
preloaded class duplicate(true)
[Resource:1196] 10  ->  [Resource:1197] 10
[Resource:1196] 22  ->  [Resource:1199] 10
class by name  duplicate(true)
[Resource:1201] 10  ->  [Resource:1202] 10
[Resource:1201] 22  ->  [Resource:1204] 10
class by name  duplicate(false)
[Resource:1206] 10  ->  [Resource:1207] 10
[Resource:1206] 22  ->  [Resource:1208] 10

@phaitonican
Copy link

id love to have a duplicate() functions which also duplicates the internal variables, because I use a class as a Data Structure and once I duplicate it (with whatever paremeters, if true or 4), the variables stay on but all are empty. Its basicallly a preload().new() but duplicate should exactly duplicate that class.

Now I added own duplicate function for the data structure class like above, but this is just a temporary solution.

@cloewen8
Copy link

Confirmed, the bug is still in Godot 3.3.

I have a particle resource with a color (purple by default). I set the color before adding it. The simulation function duplicates it before adding it. It should be the set color, but it remains purple.
Resource:

var color = Color.purple

Adding code:

var water = Fluid2DParticle.new()
water.color = Color.blue
fluids.fill_area(Rect2(start, size), water)

The fill_area function:

func fill_area(area: Rect2, p: Fluid2DParticle):
	for x in range(area.position.x, area.end.x):
		for y in range(area.position.y, area.end.y):
			_add_point(Vector2(x, y), p.duplicate())
	update()

@MikeSchulze
Copy link

You can use your own clone function as workaround, i use this solution.

func deep_clone(source :Object) :
	var clone = source.duplicate()
	# copy all property values
	for property in source.get_property_list():
		var property_name = property["name"]
		clone.set(property_name, source.get(property_name))
	
	if source is Node:
		# remove incomplete duplicated childs
		for child in clone.get_children():
			clone.remove_child(child)
			child.free()
		assert(clone.get_child_count() == 0)
		# clone childs
		for child in source.get_children():
			clone.add_child(deep_clone(child))

@Calinou
Copy link
Member

Calinou commented May 23, 2021

Duplicate of #3393.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants