I'm to sidestep the question a little, because I'm going to suggest to not use ButtonGroup
at all.
First, why not ButtonGroup
?
For what I understand the BaseButton
s register themselves with the ButtonGroup
, but the ButtonGroup
is local to the scene by default, and that is problematic when nesting the scene inside of another one.
We can implement the functionality of your code without ButtonGroup
at all, and I don't think these kind of menu needs a ButtonGroup
at all.
ButtonGroup
prevents multiple buttons to stay pressed at the same time (think radio buttons or mutually exclusive toggle buttons), but that is not necessary if the buttons cannot stay pressed.
First, we want to connect the pressed
signal of the BaseButton
s from code. We already have a container MenuVContainer
, let us use it:
extends Control
func _ready() -> void:
for i in get_node("MenuVContainer").get_children():
var button := i as BaseButton
if is_instance_valid(button):
button.connect("pressed", self, "button_pressed")
Here we are iterating over all the children of MenuVContainer
. And we will try to cast them as BaseButton
with i as BaseButton
(which results in null
if it wasn't a BaseButton
, thus checking if the instance is valid allows us to skip anything that isn't a BaseButton
). And, of course, we connect the signal.
Ah, next you want to know which button was pressed. Ok, no matter, we are going to bind that on the signal connection, like this:
extends Control
func _ready() -> void:
for i in get_node("MenuVContainer").get_children():
var button := i as BaseButton
if is_instance_valid(button):
button.connect("pressed", self, "button_pressed", [button])
And now button_pressed
will get it as a parameter:
extends Control
func _ready() -> void:
for i in get_node("MenuVContainer").get_children():
var button := i as BaseButton
if is_instance_valid(button):
button.connect("pressed", self, "button_pressed", [button])
func button_pressed(pressed_button:BaseButton) -> void:
pass
And, of course, you can check which one you got a do something accordingly:
extends Control
func _ready() -> void:
for i in get_node("MenuVContainer").get_children():
var button := i as BaseButton
if is_instance_valid(button):
button.connect("pressed", self, "button_pressed", [button])
func button_pressed(pressed_button:BaseButton) -> void:
var button_method := pressed_button.name
if button_method == "NewGameButton": print('Restarting the game')
if button_method == "OptionsButton": print('Opening the Options screen')
if button_method == "ExitButton": print('Quiting the game')
Here match
would work too:
extends Control
func _ready() -> void:
for i in get_node("MenuVContainer").get_children():
var button := i as BaseButton
if is_instance_valid(button):
button.connect("pressed", self, "button_pressed", [button])
func button_pressed(pressed_button:BaseButton) -> void:
match pressed_button.name:
"NewGameButton":
print('Restarting the game')
"OptionsButton":
print('Opening the Options screen')
"ExitButton":
print('Quiting the game')
You could even call methods by those names:
extends Control
func _ready() -> void:
for i in get_node("MenuVContainer").get_children():
var button := i as BaseButton
if is_instance_valid(button):
button.connect("pressed", self, "button_pressed", [button])
func button_pressed(pressed_button:BaseButton) -> void:
if has_method(pressed_button.name):
call(pressed_button.name)
func NewGameButton() -> void:
print('Restarting the game')
func OptionsButton() -> void:
print('Opening the Options screen')
func ExitButton() -> void:
print('Quiting the game')
Wait, if we are calling methods, why not connect them directly? You still have to write what happens for each button anyway.
extends Control
func _ready() -> void:
get_node("MenuVContainer/NewGameButton").connect("pressed", self, "NewGameButton")
get_node("MenuVContainer/OptionsButton").connect("pressed", self, "OptionsButton")
get_node("MenuVContainer/ExitButton").connect("pressed", self, "ExitButton")
func NewGameButton() -> void:
print('Restarting the game')
func OptionsButton() -> void:
print('Opening the Options screen')
func ExitButton() -> void:
print('Quiting the game')
If we are connecting buttons to methods. Why not do that from the editor?
For each button go to the Node panel and then on the Signals tab, double click "pressed", and then select the root node of you scene (the dialog also allows you to change the name of the method it will connect the signal to and set other settings). And you will end up with code that looks like this:
extends Control
func _on_NewGameButton_pressed() -> void:
print('Restarting the game')
func _on_OptionsButton_pressed() -> void:
print('Opening the Options screen')
func _on_ExitButton_pressed() -> void:
print('Quiting the game')
Yes, do the default thing.