Bind

Using bind() method is useful when connecting a signal.

In fact, bind is not a method for signal but for function (or Callable class in Godot).

For example, we have three button on our start menu.

@onready var start: Button = %Start
@onready var settings: Button = %Settings
@onready var quit: Button = %Quit

Then we can bind the start event in _ready() method, and parse some custom parameter using bind() function. For example:

func _ready() -> void:
start.pressed.connect(handle_menu_press.bind(start))
settings.pressed.connect(handle_menu_press.bind(settings))
quit.pressed.connect(handle_menu_press.bind(quit))

The code above showing, we connect the handle_menu_press function to the button’s pressed signal. But we are binding the start button (itself) as the parameters for the method.

Confused? Don’t worry, keep reading and I’ll explain it below.

What should handle_menu_press() function do?

func handle_menu_press(button_pressed: Button):
match button_pressed:
start:
start_game()
settings:
open_settings()
quit:
quit_game()

The code about show that, the handle_menu_press function received a Button type of parameters. We already parse into via bind function. So for now, when the handle_menu_press() function is called, it will also know which button is pressed, and we just need to process each button’s code logic to make them function well.

For example, when we pressed Settings button, the function will call like this handle_menu_press(setting) , then inside the function, the code determine which button is pressed (since all buttons will call the handle_menu_press) using match case, then it will open_settings() as the running result.

Bubble signal

For example, We have a Hero (Character2D) scene in our game, and inside the scene tree, we have a PowerUp node (Node2D) below it. Here is the code of PowerUp node:

# powerup.gd

signal powerup_started(id: int)
signal powerup_ended

func pickup_powerup(id: int) -> void:
powerup_started.emit(id)
# Other powerup logic here (start timer, define timeout, store type, etc...)

func end_powerup() -> void:
powerup_ended.emit()
# Other logic here (clear type, etc...)

It is very easy to receive the signal from PowerUp by Hero. But, what if in case we need to let the Node higher than Hero (like game world, or something above it) to listen to the powerup_started signal?

We may use the lambda inside Hero code, and bubble the signal up via the code below

# hero.gd

signal powerup_started(id: int)
signal powerup_ended

@onready var powerup: PowerUp = $PowerUp

func _ready() -> void:
# Lambda bubbers
powerup.powerup_started.connect(func (id): powerup_started.emit(id))
powerup.powerup_ended.connect(func (): powerup_ended.emit())

The example above, we use lambda expression ⇒ func (id): powerup_started.emit(id) and func (): powerup_ended.emit() to bubble up the signal (To emit the signal from Hero routed from PowerUp)

So now, the Hero’s parent node can listen the powerup_started and powerup_ended signal from the PowerUp node inside the Hero node.

Event Bus

We create a event.gd script and make it Autoload via Project Settings so it can be access from anywhere in our game. For example:

# event.gd

extend Node

signal language_changed(lang_id)

Then, we connect the signal inside our Settings menu (or any other way it will change your game language) by:

# for example in settings.gd

extend Controls

func change_language(lang_id: int)
Event.language_change.emit(lang_id)

We can connect the signal from anywhere, and it will working by using these code (where you need to change the language when the language is changed)

func _ready() -> void:
Event.language_change.connect(_on_language_change)

# Process your language change logic right here.
func _on_language_change(lang_id: int):
pass # Change texts and etc...

References documentations

https://docs.godotengine.org/en/stable/classes/class_callable.html#class-callable-method-bind