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

Calling duplicate(true) on custom Resource returns empty Resource. #33079

Closed
Zoomulator opened this issue Oct 26, 2019 · 4 comments · Fixed by #71142
Closed

Calling duplicate(true) on custom Resource returns empty Resource. #33079

Zoomulator opened this issue Oct 26, 2019 · 4 comments · Fixed by #71142
Assignees
Milestone

Comments

@Zoomulator
Copy link

Godot version:
3.1.1

OS/device including version:
Windows 10.0.18362

Issue description:
Resource.duplicate(true) doesn't work for a custom Resource.

Steps to reproduce:

  • Define a class that extends Resource.
  • Instance the new class and make a deep duplicate (duplicate(true)).
  • The resulting object does not contain the same script or any of the data of the original.

Minimal reproduction project:

extends Node

class MyResource:
	extends Resource
	export(String) var prop

func _ready():
	var r0 = MyResource.new()
	r0.prop = "FOO"
	test1(r0)
	test2(r0)
	var r1 = r0.duplicate()
	var r2 = r0.duplicate(true)
	test1(r1)
	test2(r1)
	test1(r2) # Fails
	test2(r2) # Fails

func test1(r):
	print("Test 1: " + r.prop)

func test2(r: MyResource):
	print("Test 2: " + r.prop)

The two tests pass for the first clone r1, but both tests fail for the deep duplicate r2.

For r2, test1 throws invalid get index 'prop' (on base: 'Resource()') and test2 throws invalid get index 'prop' (on base: 'Nil').

So it seems duplicate(true) just returns an empty resource.

Hypothesis

I discovered that r0 and r1 has the same script but r2 has a different script (print(r0.get_script())). Printing out r0.get_property_list() shows that the Script property's usage is 7 (the default), which should cause it to be duplicated on a duplicate(true).

{class_name:Script, hint:17, hint_string:Script, name:script, type:17, usage:7}

Is this expected? Why would you want the script itself to be duplicated into a new instance? I was fully expecting it to just copy the data and retain the type/script of the original. I was not expecting it to essentially create a new type by duplicating the script resource.

I would suspect that the duplication of the script property is what causes the typing to fail in test2 (discarding the object and passing Nil), but I would've expected it to still find the property in test1. Would the duplicated script fail because the MyResource class is already registered and just silently be thrown away, thus never initializing the object's properties? There are unfortunately no errors to give a clue to what happens here.

@Goutte
Copy link
Contributor

Goutte commented Mar 28, 2020

Confirming this is still happening in Godot 3.2.1, albeit only in exported builds. (both Windows and Linux)

@neikeq neikeq added this to the 4.0 milestone May 22, 2020
@kayomn
Copy link
Contributor

kayomn commented Jun 6, 2020

I'm experiencing a likely overlapping issue with Godot 3.2.1 Mono where calling Resource::duplicate(bool) with false on a custom resource written using a C# script is returning an initialized but empty Resource instance of the same type.

Here I am using a C# Resource-derived script called WeaponItem.

Name: 9mm Pistol
Information: Lightweight and reliable handgun
--- DUPLICATED ---
Name:
Information:

@geneishouko
Copy link

I have this problem by calling Resource::duplicate(true) on a custom C# resource. The debugger outputs the following error:

E 0:00:02.801   can_instance: Cannot instance script because the class '' could not be found. Script: ''.
  <C++ Error>   Method failed. Returning: __null
  <C++ Source>  modules/mono/csharp_script.cpp:2942 @ can_instance()
  <Stack Trace> :0 @ Godot.Resource Godot.NativeCalls.godot_icall_1_722(IntPtr , IntPtr , Boolean )()
                Resource.cs:208 @ Godot.Resource Godot.Resource.Duplicate(Boolean )()
                DuplicateTest.cs:26 @ void DuplicateTest.DuplicateResource()()

Here's a minimal working reproduction C# project
CSharpDuplicateTest.zip

@rosshadden
Copy link
Contributor

rosshadden commented Feb 27, 2021

I believe this may be the culprit behind what I have been running into as well (which I posted about here in the discord help channel). If you export a duplicated resource, it shows in the inspector as Empty. This backs up what you are saying about it actually being empty.

# export non-duplicated resource, which is the same instance everywhere
export(Resource) var normal = preload("path/to/resource")

# export duplicated resource
# (does the same thing if you store the preloaded resource into a constant and then just duplicate it here)
export(Resource) var duplicated = preload("path/to/resource").duplicate()

image

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