I am trying to set up a toggle music on/off button in my UI widget.
I’m initiating the sound file in my PlayerController.
I would like to be able to Toggle the volume on/off from my widget. And the music should only play while the widget is active. When I remove the widget from parent I would like to make sure the music stops.
Here’s my set up so far:
In PlayerController I’m adding the wav file as an audio component. I created a function and execute it after adding the widget.
This part works as intended:
My UI widget loads first and the music starts playing.
In my UI widget I cast to Player Controller and try to call that function.
When I click the button, instead of stopping the music, it seems to start from the beginning overlapping over and over on each click starting from the beginning of the track.
This is how I’m calling the function from the widget EG:
What am I doing wrong? How is this usually done? I only want the music to be playable if the widget is active. (And the user chooses not to disable it )
instead, set a boolean for when music is active. The toggle can then just be NOT bMusicPlaying = bMusicPlaying
(this just makes the boolean opposite of whatever it is, and then stores that)
the problem with flip flop, especially on a widget, is that it does not remember its own state. so if widget is removed or constructed a new one or whatever, the flip-flop may not actually be toggling. Whereas the boolean on the player controller is cached, so it holds its state in memory.
to make debug easy you can right click on the boolean and set Watch This value. Then slide the blueprint onto second monitor or whereever you can see it while in play mode and then press the widget buttons. You should see the value changing in real time. You can do the same thing with the flip flop node. The execution wires will highlight when they fire. This will help you see what is actually happening.
watch the execution wires light up when you press the button though.
You’ll see that the execution flow goes through the boolean, sets it, then… Adds audio component.
So the boolean is getting changed. Watch the value and you will see that with your own eyes.
But, what is not happening is that you aren’t doing anything with the boolean yet! Lol.
So you need to put it to use.
The way to do that is make a Branch node after setting the boolean. The branch node will act like how you had the flip flop. The boolean goes into the branch as the input, and from the True you can set the audio component, and from false you disable it.
This will act the same way as you had before, except that it will always work, even if you destroy the widget or call the function from somewhere else.
Fair enough… What do I need to do on the False branch? Is there a node that removes the audio component?
As of right now I have the same add audio component with the volume set to 0. But that still gives me the same issue.
I do not have an option on right click to Watch This value for the boolean
Also, is there a reason to create a new component every time? Maybe create it once and then the widget can just pause and unpause it. Why waste resources.
Ok, I’m either an idiot… or… a bigger idiot.
I can’t figure out what’s wrong for the life of me.
Here’s my full setup:
PlayerController begin play → at the end, after creating the MainMenu widget I add the ToggleMusic function (which is built in the PlayerController)
Well then… this gave me an idea… if I want to add a slider in the widget to control the volume… is there a node I could add in the PlayerController to update the value of the slider and plug it into a volume pin? I’m thinking a float between 0 and 1??? something along those lines? This is just extra, but why not? (if possible)
you can access the sounds volume by dragging of the Music reference and type Volume. Should be a Setter function for that.
As for using a slider, unreal has some built in slider widgets I believe, but I haven’t used them.
What the slider will do is output a 0-1 value though, and you can then use that to adjust your music volume. You may need to use a Map Ranged Clamped node to set the range of volume that you want 0-1 to cover.
Not sure why you pass this stuff back to the player controller though? It’s all stuff that is only associated with the UI menu isn’t it?
You do not need any code in the widget. Everything is in the pic.
Callback delegates are the bread & butter of comms. This sounds like the perfect use-case scenario. Keep your script as is, but add the slider onValueChanged and adjust the volume (stuff in the red frame) - see if it works.
oh yeah i hadnt really looked into the details of where all the code is happening or why.
but what everynone is showing here is probably the simplest thing to do because it has fewest moving parts (less chance to make mistakes and get confused)
You could do it all in here. We don’t know what blueprints it is, not sure if you mentioned that. You add the component here, you create the widget here. All the puzzle pieces are here.
The widget communicates back to this blueprints via delegates - the red wires.
At this point it’s up to you if you need to get the PC involved. Does it need to know anything about this stuff?