Attention | Topic was automatically imported from the old Question2Answer platform. | |
Asked By | dr-pop |
My problem is how to have a child node ask for data from a parent node and receive/retrieve it within the same function, so that it can be returned. A seemingly simple task but it’s been breaking my brain for the past two days.
I want to note I have avoided to call parent node functions or variables using get_parent(), because I understood this make your node structure brittle and unstable. (“Call down, signal up.”)
So in (this simplified version of) my game, I have two nodes: ‘TestParent’ and ‘TestChild’. I store the game data in a dictionary in TestParent. The gameplay takes place in TestChild, which needs access to the data in TestParent. TestChild has a button that calls the function retrieve()
in order to get and print the value for key2
from the dictionary in TestParent.
TestParent.gd:
extends Node2D
var child_scene = load("res://TestChild.tscn")
var child_instance
var dict = {
"key1" : 1,
"key2" : 2,
"key3" : 3
}
func _ready():
child_instance = child_scene.instance()
add_child(child_instance)
child_instance.connect("record", self, "record")
child_instance.connect("get", self, "get")
func record(location, data):
dict[location] = data
func get(location):
var data = dict[location]
# yield(get_tree().create_timer(1.0), "timeout") # (Simulate processing delay.)
child_instance.store(location, data)
TestChild.gd:
extends Node2D
var temp_memory = {}
signal record(location, data)
func record(location, data):
emit_signal("record", location, data)
signal get(location)
func retrieve(location):
emit_signal("get", location)
return temp_memory[location]
func store(location, data):
temp_memory[location] = data
func _on_Button_pressed():
print(retrieve("key2"))
This version works, but only because Godot manages to store the data in temp_memory[location]
before the function retrieve() in TestChild.gd runs the line return temp_memory[location]
. However, this is very fragile, because if this process takes a bit longer, temp_memory[location]
will be returned as null or as an outdated value. This can be simulated by adding the commented out line in get()
.
So to prevent this instability, I wanted to add a command that would tell TestChild to wait with returning the value until the value has been stored in temp_memory
. I thought yield()
in combination with a signal would work for this. See the set-up below for my changes.
TestChild.gd (with yield()
and signal)
extends Node2D
var temp_memory = {}
signal record(location, data)
func record(location, data):
emit_signal("record", location, data)
signal get(location)
func retrieve(location):
emit_signal("get", location)
yield(self, "data_stored") #Added
return temp_memory[location]
signal data_stored() #Added
func store(location, data):
temp_memory[location] = data
emit_signal("data_stored") #Added
func _on_Button_pressed():
print(retrieve("key2"))
The problem with this script, however, is that instead of waiting for a signal, yield()
actually returns data to _on_Button_pressed()
. When printed, this data appears like this, with the number constantly changing (I suppose it’s the delta or number of frames?):
[GDScriptFunctionState:1264]
What do I not understand about yield()
that I should know? I thought yield()
would make a function pause and wait until a signal was received/observed. However, instead of waiting, the function returns even quicker. What would be a better way to do this?
Ugh, I hate that topic myself, but I have a feeling this will enlighten You enough :
https://www.youtube.com/watch?v=XJU0P6M5IKg
Basically yield returns frozen state of function, for other function to retrieve. So it is exactly the function You needed for Your idea, but didn’t find yet :).
Inces | 2021-12-09 20:31
Thanks for your help. I did watch that video before, but it still left me with a lot of questions. I will watch it again, however!
dr-pop | 2021-12-12 22:08