Hi!
At the moment, I have the problem that I may have structured my level incorrectly from a strategic point of view.
-
I have individual scenes containing elements such as platforms and blocks. Some of them contain action scripts, like this SwitchBlock. I want to add signals that are emitted when an action occurs.
-
These elements (as well as theSwitchBlock) are assembled in their own level scene.
-
The level scene is ultimately placed in the MAIN scene with a GameManager script.
How can I connect to the signal from the SwitchBlock element to the GameManager script?
It only inserts itself into its own SwitchBlock script, but not further up in the hierarchy.
I think I’ve made it too complicated because I wanted to keep things organized, and now I don’t know what to do. What can I do?
Thank you.
Jeff
Propagate the signal up the tree, or globalize it.
1 Like
To expand a bit on the answer @normalized gave
You could connect a handler to the signal directly
main.child_scene.switch_block.connect(signal_handler)
Or use a global signal bus
class SwitchBlock:
GlobalBus.signal.emit()
And have the handler in the appropriate scene watch the bus.
I personally prefer the first approach.
For what it’s worth, I do not think there is anything wrong with your level structure. From what I can tell it closely resembles what I use, and I use a fair number of signals.
1 Like
Thank you very much for your answers. Unfortunately, I haven’t been able to get it to work (direct handler in my GameManager script). I am now using an ugly solution where I park the signals in an own script and load them via autoload. This allows me to access these signals from anywhere.
That is not an ugly solution but basically what a global signal bus is. Here is a quick guide by GDQuest on global event singletons. You are probably doing something similar to this already. Connecting signals directly is easy in a small project, but the more your project grows the harder it is to keep track of all the connections and figuring out how to group them in a good way. By using a global even singleton you have one place to manage your signals.
In other systems this is called an event broker, or an event manager. It is basically a class that helps keep track on who needs to subscribe to whom.
Hope this helps!
1 Like
Ok, so you have a GameManager. If it’s not an autoload already, it should be with a name like that. I can’t read your code cause it’s too small in the screen shot, so I’m calling the signal my_action.
Add this to game_manager.gd:
signal my_action
Add this to the SwitchBlock script when you want to emit the signal:
GameManager.my_action.emit()
Add this to anything that needs to know when my_action was triggered:
func _ready() -> void:
GameManager.my_action.connect(_on_my_action)
func _on_my_action() -> void:
# Do stuff
On a related, but separate issue, consider renaming GameManager to Game. It will change how you think about how to use the object. Nothing should be a “Manager” if you can avoid it. It will result in anti-patterns forming in your code.
Once you have the above code working, you can consider a refactor later if you find that you don’t need a global signal bus to pass these signals.
For example, I have a StateMachine attached to every player/enemy/NPC in my game. They connect to signals from whatever they are attached to. So if The character dies, it send out an “I died” signal, and anything that needs to listen to it pays attention to the player.
1 Like
Thank you for your valuable tips.
1 Like