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

Cyclic dependencies in resource arrays turn null on loading with ResourceLoader #86641

Closed
mmyumu opened this issue Dec 30, 2023 · 1 comment
Closed

Comments

@mmyumu
Copy link

mmyumu commented Dec 30, 2023

Tested versions

Reproducible in Godot 4.2.1 stable.
This issue does not occur in versions prior to 4.2, as cyclic dependencies in resources were not functional.

System information

Godot v4.2.1.stable - Windows 10.0.22621 - Vulkan (Forward+) - dedicated NVIDIA GeForce RTX 2080 (NVIDIA; 31.0.15.4601) - Intel(R) Core(TM) i7-9700K CPU @ 3.60GHz (8 Threads)

Issue description

I am working with two resource types: RefA and RefB.
Within the RefA resource, I have an array containing elements of type RefB, declared as @export var ref_b_list: Array[RefB].
In the RefB resource, there's a simple reference to RefA, declared as @export var ref_a: RefA.

I use ResourceSaver to serialize the RefA resource. However, when I load this resource back using ResourceLoader, the ref_a reference in the RefB objects within the ref_b_list array is set to null.

This issue seems to be specific to the usage of an Array. If I replace the Array[RefB] with a single instance of RefB, the serialization and subsequent loading maintain the ref_a reference correctly.

Steps to reproduce

  1. Create a ref_a.gd script :
class_name RefA extends Resource

@export var ref_b_list: Array[RefB]
  1. Create a ref_b.gd script:
class_name RefB extends Resource

@export var ref_a: RefA
  1. Create a main scene (Node) with attached script:
extends Node

func _ready():
	var ref_b: RefB = RefB.new()
	
	var ref_a: RefA = RefA.new()
	ref_a.ref_b_list.append(ref_b)
	ref_b.ref_a = ref_a
	
	var result = ResourceSaver.save(ref_a, "user://test_data.res")
	var loaded_ref_a = ResourceLoader.load("user://test_data.res")
	
	print("ref_a.ref_b_list[0].ref_a=%s"% ref_a.ref_b_list[0].ref_a)
	print("loaded_ref_a.ref_b_list[0].ref_a=%s"% loaded_ref_a.ref_b_list[0].ref_a)
  1. Run the main scene and checks the output:
ref_a.ref_b_list[0].ref_a=<Resource#-9223372009776347953>
loaded_ref_a.ref_b_list[0].ref_a=<null>

Minimal reproduction project (MRP)

bug_cross_reference.zip

The project basically contains what is described in step reproduction except I added a single ref_b variable as a sanity check.
When executing it you will see in the output something like :

ref_a.ref_b=<Resource#-9223372009793125170>
ref_a.ref_b_list[0].ref_a=<Resource#-9223372009776347953>
loaded_ref_a.ref_b=<Resource#-9223372009575021357>
loaded_ref_a.ref_b_list[0].ref_a=<null>
@AThousandShips
Copy link
Member

This is not supported, and shouldn't IMO be used as it introduces memory management breaking behavior

Since this isn't supported and by design I'm closing this in favor of a proposal which suggests supporting this, I suggest adding your support there

Thank you for your report

@AThousandShips AThousandShips closed this as not planned Won't fix, can't repro, duplicate, stale Dec 30, 2023
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

2 participants