I'm experiencing an error with await
being triggered multiple times inside a loop.
What the code is supposed to do is loop through all the empires, telling them to take their turns and then await
ing their completion before triggering the next empire. This works for the first turn (the player's turn), but when an AI tries to call endTurn()
, I get the error:
E 0:01:08:0911 Map.gd:419 @ endTurn(): Resumed function 'beginRound()' after await, but script is gone.
At script: res://scripts/HostGameMenu.gd:197
<C++ Error> Method/function failed. Returning: Variant()
<C++ Source> modules/gdscript/gdscript_function.cpp:197 @ resume()
<Stack Trace> Map.gd:419 @ endTurn()
Tribe.gd:221 @ takeTurn()
Map.gd:414 @ beginNewTurn()
HostGameMenu.gd:196 @ beginRound()
Map.gd:419 @ endTurn()
Map.gd:1912 @ endEmpireTurn()
Script One Functions:
func beginRound():
for i in range(empireTurnOrder.size()):
empireTurnIndex = i #the only purpose this serves is being able to easily access whose turn it is for debugging from outside the for loop
gameMap.beginNewTurn.rpc(empireTurnOrder[empireTurnIndex]) #empireTurnOrder is a PackedStringArray
await gameMap.beginNextTurn
gameMap.endRound.rpc() #gameMap points to the node containing Script Two
Script Two Functions:
signal beginNextTurn
@rpc("any_peer", "call_local", "reliable")
func beginNewTurn(nextEmpire: String) -> void:
var empire = getEmpire(nextEmpire)
if empire.playerId != -1 and empire.playerId != userEmpire.playerId: #check is only for multiplayer, which is not the case for my tests. userEmpire is a reference to the empire node (node of Script Three) that the player controls
pass
else:
if empire.playerId == userEmpire.playerId:
#UI edits, irrelevant
empire.takeTurn() #empire points to the node(s) of Script Three
func endTurn():
if not serverHandler.inServer or multiplayer.get_unique_id() == 1: #serverHandler points to the node of Script One. inServer will always be true for singleplayer, which I am testing
print(is_instance_valid(serverHandler))
emit_signal("beginNextTurn")
func endRound():
if not serverHandler.inServer or multiplayer.get_unique_id() == 1:
serverHandler.beginRound()
func endEmpireTurn(): #button is tied to this function
#edits UI a little
endTurn()
Script Three Functions:
func takeTurn():
if playerId == -1:
map.endTurn() #map points the node of Script Two
else:
#does nothing; button press will call endTurn for players
Printed Output:
True
True
Any help is appreciated. The only other posts I found about this error were people awaiting timers in _process()
functions, and the answers to those questions were not exactly applicable to my situation.
Edit:
I added a function to Script One:
func turnEnded() -> void:
print(empireTurnOrder[empireTurnIndex] + "'s turn is over.")
and connected the beginNextTurn
signal to it, and it also printed successfully/correctly for both emissions of the signal, but the error didn't change.
Edit 2:
Just out of curiosity to see if it worked, I changed two functions, beginNewTurn and beginRound like so:
@rpc("any_peer", "call_local", "reliable")
func beginNewTurn(nextEmpire: String) -> bool:
var empire = getEmpire(nextEmpire)
if empire.playerId != -1 and empire.playerId != userEmpire.playerId:
pass
else:
if empire.playerId == userEmpire.playerId:
loadedData.get_node("ImportantMenuHub/EndTurn").set_disabled(false)
loadedData.get_node("ResourceHUD/RaiseAll").set_disabled(false)
empire.takeTurn()
await beginNextTurn
return true
func beginRound():
for i in range(empireTurnOrder.size()):
empireTurnIndex = i
await gameMap.beginNewTurn(empireTurnOrder[empireTurnIndex])
gameMap.endRound.rpc()
And this gives the error "Parameter "function" is null" on the emit_signal("beginNextTurn")
line. Now, obviously, I do want my solution to be compatible with rpc function calls, but it's very strange the signal refuses to function correctly with beginRound()
and beginNewTurn()
. The output for this, btw, is still
true
<empire 1>'s turn is over.
true
<empire 2>'s turn is over.
This is an error with Godot version 4.2.2 that has been fixed in 4.3. I'm not sure if this is an acceptable answer for this site, but it is the only one for this question.