Reputation: 11
I am trying to make a multiplayer godot game, and I want to make sure every @rpc have been read by all peers before continuing to read through the main part of the code.
So I made a variable that increases every time one of the rpc is read.
The problem is that I want to make sure that the main program is stopped while this variable is below the number of players.
I have been searching a lot for documentations, but I only came across await which uses signals (so no links to variables), while (which just completely freezes the program) and have been trying to find functions that launches anytime an if statement is true (without luck).
Upvotes: 1
Views: 1748
Reputation: 40325
No, there isn't. You need to build this.
As you found out await
works with signals. Well, you can create your own custom signals. So in the code where you increment the variable, you can either add a check, or emit a signal, or both.
For example, one way would be to define a setter for your variable, and have signal when it changes to the value you want. Then you connect or await it.
signal expected_x_reached()
var expected_x:int
var x:int:
set(mod_value):
if x == mod_value:
return
x = mod_value
if mod_value == expected_x:
expected_x_reached.emit()
Addendum: In this scenario, you might want to have a setter for expected_x
too (since x == expected_x
can become true because x
changed or because expected_x
changed). But I'll keep it as is for clarity.
Be aware that you can define a signal for when a value changes, and connect an anonymous method to check fo the value (which is useful if different parts of your code need to wait for different values):
signal x_changed(value:int)
var x:int:
set(mod_value):
if x == mod_value:
return
x = mod_value
x_changed.emit(mod_value)
In this case the method connected will get the value:
obj.x_changed.connect(
func (value:int) -> void:
if value == expected_x:
# do something, emit a signal, whatever
pass
)
If is not code you control... You might have to find an adequete existing signal. Or you need to check for it in _notification
or some other callback.
Worse case scenario you need to check every frame (because there is no notification mechanism, and you can't add one without a custom build of Godot).
You can check every frame using _process
or connecting to the process_frame
signal of the scene tree.
Using _process
could be like this:
func _process(_delta:float) -> void:
if obj.x == expected_x:
# do something, emit a signal, whatever
pass
You might do this in your existing nodes, or create a new node to keep track of the variable and emit the signal... Which other nodes can connect to.
If you were writing a loop to wait, you should be able to either:
_process
(doing one iteration each frame).await
※ on process_frame
, or on some custom signal.call_deferred
. I'll advice to not abuse this, there is a limit to how many deferred calls you can have going.※: I'll also point out that there is a drawback to awaiting: it cannot be cancelled, and a freed object cannot resume from an await (which can result in some nasty bugs). If you run into such problems, consider refactoring from await
to continuations connecting to the signal using CONNECT_ONE_SHOT
or having code to disconnect when it is appropiate. The reason being that when objects are freed, they automatically disconnect.
Upvotes: 1