godot
godot copied to clipboard
Resumed function after await, but script is gone
Tested versions
Reproducible in v4.2.2.stable.official [15073afe3]
System information
Windows 11 - Godot v4.2.2.stable.official
Issue description
I am not entirely sure about what is causing the error; however, if I had to guess, scripts that await signals that will be emitted based on player input are at risk of being deleted from memory even if the script is integral to the continuation of the program.
The exact error I receive in the MRP is as follows:
E 0:00:01:0026 NodeTwo.gd:14 @ endTurn(): Resumed function 'beginRound()' after await, but script is gone. At script: res://NodeOne.gd:13 <C++ Error> Method/function failed. Returning: Variant() <C++ Source> modules/gdscript/gdscript_function.cpp:197 @ resume() <Stack Trace> NodeTwo.gd:14 @ endTurn() NodeThree.gd:11 @ takeTurn() NodeTwo.gd:10 @ beginNewTurn() NodeOne.gd:11 @ beginRound() NodeTwo.gd:14 @ endTurn() NodeTwo.gd:17 @ manualEndTurn()
E 0:00:01:0026 NodeTwo.gd:14 @ endTurn(): Attempt to disconnect a nonexistent connection from 'NodeTwo:<Node3D#23941088455>'. Signal: 'beginNextTurn', callable: 'GDScriptFunctionState::_signal_callback'. <C++ Error> Condition "!s->slot_map.has(*p_callable.get_base_comparator())" is true. Returning: false <C++ Source> core/object/object.cpp:1420 @ _disconnect() <Stack Trace> NodeTwo.gd:14 @ endTurn() NodeTwo.gd:17 @ manualEndTurn()
Steps to reproduce
Create a node for the head of the scene, then give it 3 children. It does not matter what kind of node you use; in the MRP I used the nodes that were giving me problems in my actual project, but testing with those nodes switched out for basic Nodes did not change the results.
I named the three children NodeOne, NodeTwo, and NodeThree in the MRP, and I will use those names to refer to them throughout the rest of the instructions.
Give each of the children a script. For the first node, write
@onready var node2 = get_parent().get_node("NodeTwo")
func _ready():
await get_tree().process_frame
beginRound()
func beginRound():
for i in range(3):
node2.beginNewTurn()
print("waiting for turn to end")
await node2.beginNextTurn
For NodeTwo:
signal beginNextTurn
@onready var node1 = get_parent().get_node("NodeOne")
@onready var node3 = get_parent().get_node("NodeThree")
func beginNewTurn() -> void:
node3.takeTurn()
func endTurn():
print(is_instance_valid(node1))
emit_signal("beginNextTurn")
func manualEndTurn():
endTurn()
And finally, for NodeThree:
@onready var node2 = get_parent().get_node("NodeTwo")
var endManually: bool = true
func takeTurn():
if endManually:
pass
else:
node2.endTurn()
endManually = not endManually
Lastly, create a button and connect its pressed signal to NodeTwo's manualEndTurn()
. It does not matter where you put the button node in the tree. When you run the project, clicking the button should give you the same error.
Minimal reproduction project (MRP)
https://github.com/FrasherGray/AwaitingSignalErrorMRP