0 votes

Assume we have a board game with the following scene setup

Root
- Player
- Board
- Scoreboard UI

When the Player lands on a space and (say) gets a point, they emit a signal to let the scoreboard know to update, and then proceeds with the rest of its turn:

emit_signal("scoreboard_update", 1)
do_other_stuff()

The Scoreboard UI is then listening for that signal ("scoreboard_update") to update its display. However, say that this updating takes some time (an animation, musical fanfare, etc.) and we want Player to wait for the updating to finish before it proceeds (to do_other_stuff()). Is the best way to accomplish this via waiting for a second signal from Scoreboard UI? As in

emit_signal("scoreboard_update", 1)
yield($"../Scoreboard UI", "scoreboard_updated")
do_other_stuff()

Or, separate out the next action into a separate function connected to the "scoreboard_updated" signal:

func on_Scoreboard_UI_updated():
    do_other_stuff()

...or something else?

Godot version 3.3.3
in Engine by (15 points)

1 Answer

+1 vote
Best answer

If an object emits a signal, it should not be concerned with the matter in which said signal is processed. There could always be one listener, multiple, or none. If you want the player to emit a signal then be frozen until an external factor occurs, you could implement a state system which renders the player frozen indefinitely, and let your controller trigger a state change in the player for resuming activities after the controller is done with whatever it needs to do.

by (829 points)
selected by

Thanks for the answer. Player actually already has a state machine child node, and you're right that I could add a WaitingForScoreboard state. However, if I let the scoreboard trigger a state change, couldn't there be a race condition if the scoreboard acts fast enough? i.e.

  • player emits signal to scoreboard
  • (a)
  • player emits state_change signal to itself
  • (b)
  • player changes state to WaitingForScoreboard

If the scoreboard processes the signal at (a) or (b) and emits back to the player to resume, it won't be in the correct state at that time. On some related questions, I saw some comments about using call_deferred to avoid this, but I'm a bit fuzzy about how to use it.

The player could change states as soon as it emits the scoreboard signal; emitting a signal for self-consumption would eventually trigger a method anyway, so it would make sense to call it immediately instead. If you want to notify other objects of the player's state change, you could for example add a setter to the state and emit the signal inside the setter.

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.