I’m getting massively confused and mixed up between Godot 3 and 4 regarding signals. I’ve been trying to send a signal from my UIManager (button click) to my GameManager for the past hour but can’t get it too work. How is this done in Godot 4?
I have found a way to make it work in the sense it does what I want it to, however I’m almost certain it’s not the correct way. This is just emitting a signal directly from GameManager to itself, correct? I assume this is not good practice.
You definitely got confused somewhere on the way
In general, you should define and emit a signal from one node, and then connect and handle the signal in another node (or nodes).
In your case, if you want the GameManager to react to a pressed signal that is in your UIManager, then the UIManager should define a signal, emit the signal, and GameManager should connect to it and handle the signal. You don’t need to define the signal on both nodes, only on the node that emits the signal.
Remember to additionally connect your actual button’s pressed signal to a _on_build_mode_button_pressed method on UIManager node, either in Inspector, or in code.
I appreciate the help, unfortunately It still doesn’t work for me. I get “Build Mode button pressed!” but not the second print statement. I also re-read the documentation and think I understand it reasonably well but can’t for the life of me see the issue - so perhaps I don’t!
Not sure if it helps but:
GameManager and UIManager are not in the same scene. UIManager is attached to the main node in my UI scene and GameManager is just a script. Both are Autoload Singletons.
I changed the method name in GameManager as I think it had a mistype but still, it doesn’t work for me.
@wchc Interesting. I must have messed something else up along the way but I can’t think what else it could be.
@matheusmdx That’s a point. I wanted to use signals to keep it flexible and as de-coupled as possible. There will be more than one system that needs to react to the button press but as I’m typing this… perhaps that won’t be such as issue. I suppose it’s the fact I can’t figure out why it’s not working that’s driving me crazy more than actually needing it to work.
If you don’t mind, you can share your project copy through GitHub, I can have a look tomorrow to see if I can find a cause why it behaves differently in your project vs mine.
I downloaded your project and i found the issue, the problem here is because you’re creating an autoload with your ui_manager.gd but also use the same script in the ui.tscn and that is a terrible idea because is prone to bugs (like… this one).
You’re connecting your signal in the autoload script, but your autoload don’t create the button to be pressed, the button exist in the ui.tscn that also has the same script, but will be different instances, so when you click the button, you’ll trigger the script inside the ui.tscn, not the one from the autoload.
The solution is simple, delete the ui.tscn instance in the main.tscn and instead ui_manager.gd be the autoload, make the ui.tscn as the autoload, so you’ll bring the script with the button and everything will work as your expect.
That 100% works, and makes sense! My lack of experience clearly showing with both Godot and some fundamental programming principles. Just to clarify, I removed the UI scene instance from my Main scene all together and will now rely on the auto loaded UI scene for the entire games UI - is that correct?
The only downside I see is it now missing from the 2D editor view as overlay (and main scene tree) but that’s not a problem for this. It actually makes a lot of sense to have the entire UI as a separate single source of truth I think, at least for the type of game I’m trying to make.
Is this a common design pattern, loading entire game wide scenes (like a UI) in autoload instead of having them as instances of the main scene? Would the tradeoff be that you always have the entire scene in memory? Which in this case doesn’t make much difference as the same UI elements exists in basically the entire game anyway.
Once again, thank you for the help! If we’re honest the game code is going to be a huge mess anyway once I’ve finished with it, but hopefully I can flesh out a basic idea which is my only goal.
I think is a valid option because as you said, is a part of the game that’ll be visible 99% of the time and yes, the cost is have in the memory all the time, but generally the UI isn’t big enough to make a considerable impact.