Problems are opportunities - Slider snapping in UE4
I wanted to use a UMG slider to simulate tabbed navigation while also still acting as a slider. Setting up events to switch menu panels driven by slider changes isn't hard (at least if the slider only has a few increments), but before going so far, I had to figure out how to just snap or step the slider at all, so I came up with this widget graph.
This is based off : https://answers.unrealengine.com/questions/219334/how-do-i-create-snaps-on-umg-slider.html
Sliders in UE4 range from 0.0 to 1.0
When you create a slider, a variable for it is created in the widget's graph (Slider_Interaction in this case). I also created variables for a soundcue SliderSound and two floats, SliderSteps and SoundGateValue.
The blueprint graph:
The first problem is a quirk of UE4. A tricky part starting out is that the SnapSlider event is what's called a Delegate (at least I believe so). You can't just create a Custom Event and drag it into the Bind Event to OnValueChanged node's Event slot. You have to drag the other way. Dragging from the Event slot prompts you to create the delegate event, which is automatically bound to the onValueChanged and even gets its own Value float added, which reflects any change to the slider value. Tricksy but cool.
The second problem is that the slider thumb image at 0.0 sort of overlaps the left margin (and at 1.0 on the right side). We can use a node called Map Range Clamped to fix that. In my case I've used literal values, working out visually that an offset of 0.125 or so places the thumb image in a good starting place.
The third problem is we want snap the slider, not drag it using float values to the sixth decimal place. Since the slider range is 0.0 to 1.0 we can multiply the current value by 10 so we can then Truncate it, so a value of 0.125 becomes 1.25 which truncates to 1 (as an int). We can then coerce the value back to a float and divide it by the number of steps in our slider (I used 7). That gives the increments the slider will snap.
The fourth problem is, that clicking on the slider will jump the thumb image to one spot ahead of where you click. If you click on the first snap spot it jumps to the second snap spot. So shoving a (float - 1.0) in there takes care of that.
The fifth problem is that, the slider can still be dragged to 0.0 and 1.0, so in a Tick event we can continually push the slider thumb to a set Min or Max value if the user drags the slider beyond the target range (0.125 to .857 in my case). This also overrides the default out of range value of 0.0 for the slider position.
The sixth problem is sound. If we add a Play Sound 2D we can add some kind of UI interact audio at the end of our OnValueChange bound event, but it will play too frequently when we drag the slider, sounding horrible. To avoid that, I set the slider's actual value to a SoundGateValue float on Tick, and convert it to a string and take the substring of the first three characters, so 0.125555 or 0.1256666 become 0.1 and then we do the same for our shifted slider value (the one we're setting on our SnapSlider event), and if they're not equal (!=) we branch our Play Sound 2D. Using a DoOnce and a Delay (of just a little longer than the audio clip duration) prevents the sound playback from overloading when dragging the slider.
[Note, in the second comment block I've grabbed a substring from a float, which is a bit bad because numbers should be handled as numbers generally. It's probably computationally cheaper to take 0.1whatnot and times it by 10 (becomes 1.whatnot), then truncate it (becomes 1.0) and divide by 10 (becomes just 0.1). But I tend to do what comes to mind and I already made the picture. There's an example of the mathsy way in the first comment block ... so I guess the image shows two ways to do a thing.]
The seventh problem is visuals. I'm still not really happy with how UE4 scales widgets all over the place, especially when you nest a slider inside a Vertical Box for instance (it tends to use aggressive horizontal and vertical space filling). So if you make a 256 slider inside of a 256 horizontal box, it might look too short, at least in the designer. Anyway, besides that, work out the image thumb width to be a clean fraction of your slider background image. So if you have 256 wide slider backdrop, and want 6 steps, then make the slider thumb 42 wide. My SliderSteps value turned out to work best at 7.0, but then there's that (float-1) in the mix.
Overall, this procedure should be a bit easier I think, but when it's working it's nice. Video below: