TDIL: The Magic of Callable.bind in GDScript

Today I learned (TDIL) about a super helpful feature in GDScript: Callable.bind. If you’re working with signals in Godot and find yourself needing to pass additional data to a single handler, Callable.bind is your new best friend.

The Problem

In many UI setups, you might have multiple buttons that trigger the same function. However, these buttons often represent different actions or carry unique context. For example: A list of character abilities with each button corresponding to a specific skill. A menu system where each button navigates to a different scene or executes a unique task. The usual approach is to connect each button’s pressed signal to the same function. But how do you tell which button triggered the signal? And what if you need to pass more data (e.g., an ID, name, or reference) to your handler?

The Solution: Callable.bind

Callable.bind allows you to attach additional arguments to a function call. This means you can make your signal handler more dynamic without writing extra boilerplate code.

The Button.button_up signal doesn’t allow any arguments to be returned to the handler function, so we solve this by binding data.

Let’s break it down with an example:

func create_chracter_button(character: Networking.Proto.Entiy) -> Button:
	var button: Button = Button.new()
	button.text = character.get_name()
	button.size.y = 100
	button.button_up.connect(on_character_button_released.bind(character))
	return button

func on_character_button_released(character: Networking.Proto.Entiy) -> void:
	print(character.get_name() + " selected")
	current_character = character
	%CharacterName.clear()
	%CharacterName.text = "[center][b]" + character.get_name() + "[/b][/center]"