UISlider - Convert GUI into interactable sliders!

UISlider - Convert relative GUI into interactable sliders!


Introduction - What is UISlider?

UISlider is a utility/tool module I made that allows you to convert UI that fits the criteria, into interactable User-Interface sliders.
It’s designed to be simple.


Features

  • Interactive Sliders: Create interactive sliders from relative GUI - works for both left and right sliding sliders!
  • Type-Annotation support: Type-annotated for better dev experience
  • Memory Optimized: Memory leak free
  • Optimization: Optimized and efficient for use
  • Simplicity: Incredibly simple to use
  • Mobile support: Works on mobile

How to use

The usage of UISlider requires some setup with UI to look and work correct.

  1. First, create a ScreenGui (or use existing one), and insert a frame. Size it accordingly for the slider. This will be the ‘holder’ for our slider thumb and filler, it is static. (Doesn’t move)

  2. Next, inside of that frame, insert another frame within the bounds of the previous frame, this will be the ‘fill’ frame that moves with the thumb button (Movable). This must have an AnchorPoint of 0 or 1 on the X, or else it won’t slide correct. If you want it to slide to the right from the left, AnchorPoint of 0 should be used on the X, if you want it to slide to the left from the right, AnchorPoint of 1 can be used.

  3. Next, create a GuiButton - which classifies as either of the two current GUI buttons in studio; TextButton or ImageButton. This is our thumb button, and what users can interact with to move the slider to move to the left or right. Recommended this is positioned on the right or left side of the fill frame from the previous step.

Your GUI should look something like this:

And your explorer should look something like this:

  1. Next, we can create the actual code
-- In a LocalScript...
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")

local UISlider = require(ReplicatedStorage.UISlider)

local player = Players.LocalPlayer
local playerGui = player.PlayerGui
-- Grab all the GUI required for the slider
-- Declare GUI's using :WaitForChild due to replication issues
local screenGui = playerGui:WaitForChild("ScreenGui")
local sliderTrack = screenGui:WaitForChild("SliderTrack")
local sliderFill = sliderTrack:WaitForChild("SliderFill")
local sliderThumb = sliderTrack:WaitForChild("SliderThumb")

-- Configuration for the slider
local CONFIG: UISlider.UISliderConfig = {
	sliderTrackFrame = sliderTrack, -- The main parent frame
	sliderFillFrame = sliderFill, -- The fill frame
	sliderThumbButton = sliderThumb, -- The thumb button
	stepSize = 0.05, -- How much to step each value (0 = no step)
	interactable = true, -- Whether the thumb button is actually interactable
	initialSliderValue = 0.5, -- The initial value of the slider from 0 to 1
}

-- Create our UISlider object
local slider = UISlider.new(CONFIG)

-- Here we can do whatever, like listen to the OnSliderValueChanged signal!
slider:OnSliderValueChanged():Connect(function(oldValue: number, newValue: number)
    -- This runs anytime the slider is changed!
	print(`Slider value changed from: {oldValue} to {newValue}`)
end)

API Reference

Functions

View
  • UISlider.fromAll(configs: {UISliderConfig}): {UISlider} - Helper function that constructs a batch of UISliders

Constructors & Methods

View
  • UISlider.new(config: UISliderConfig): UISlider - Constructs a new UISlider object

    • :SetInteractable() - Enables slider interaction

    • :SetUninteractable() - Disables slider interaction

    • :IsInteractable() - Checks whether the slider is current interactable

    • :SetValue(value: number) - Manually sets the slider to a specific value.

    • :GetValue() - Gets the current value of the slider

    • :OnSliderValueChanged() - Receives a signal that fires when the slider value changes

    • :OnSliderPressed() - Returns a signal that fires when the slider thumb is pressed down

    • :OnSliderReleased() - Returns a signal that fires when the slider thumb is released from a pressed state

    • :OnSliderHovered() - Returns a signal that fires when the slider thumb is hovered

    • :OnSliderUnhovered() - Returns a signal that fires when the slider thumb is no longer hovered

    • :SetStepSize(step: number) - Sets the step size for slider value increments

    • :Destroy() - Completely destroys the UISlider Instance

Types

View
  • UISliderConfig - Defines the overall structure of configuration for UISlider
  • UISliderInternals - Represents anything private in the class
  • UISlider - Represents anything public in the class

Conclusion

Create interactive User-Interface sliders using UISlider! It turns a relatively complex challenge into a simple, easy-to-use framework.

If you encounter any issues, let me know and I can try to help!
Please make sure to like the post if this module was helpful for you! :heart:


Changelog

Version 1.0.1 (Current)

  • Added proper mobile support

License

Free to use and modify for any Roblox projects. Credits appreciated but not required.


Installation

You can download here on Roblox Creator Store: UISlider - Convert GUI into interactable sliders!
Last Updated: 8/26/25
Author: RobloxJrTrainer
Version 1.0.1

19 Likes

what if we want to disable fill frame?

You can set it to be invisible, so that you can’t see it through the .Visible property.

Being used in (✨UPD) Sniper Tag 🎯 - Roblox, so far it seems to generally work without issue which is good however on mobile, the sliders are kinda glitched/weird, like if the user slides it too quickly it does not register the input.

1 Like

Thanks for using in your game!

But I did see the mobile issue, I plan on fixing it soon - just been a bit busy.

1 Like

Hey! Download the UISlider model again, the mobile issue should be fixed now - tested using the emulator. Completely backward compatible

1 Like

Can we get a way to just set the sliderFillFrame to nil if we want to disable fill?

I know you previously said:

However I think it would just be easier to be able to set it to nil.

1 Like

Alright, by the way i see some vars that arent used, heres some i was able to find:
in Coordinator


Same for POLLING_INTERVAL, unused var

in Connection, same as Coordinator

Another time in Nexus!


As-well, this check


wont work because of the value always being false

Filter too, ReplicatedStorage thing
For this


i decided to do
image
As ive heard storing a nil value is faster than a false value, no code that depends on this will error because it is not setting a property and instead its only a IF statement

Within main module too, ReplicatedStorage/Players

Also noticed that everytime .new is used, it will create a new InputBegan and InputEnded event on UserInputService so such should be changed to this:



Im not quite sure if having a InputBegan/InputEnded connection made on UserInputService every time a slider is created is great so i changed it to only two connections that check all, as previously it would check all but for every slider it would add 2 new connections:

In v1.0.0 i can see it only uses InputBegan/such on the slider button however that causes issues as mentioned

So i see you changed it to creating a new InputBegan and InputEnded on UserInputService for every slider.

From what i see not too many connections are required as it works with 1 InputBegan, 1 InputEnded and a HeartBeat connection for when a slider is being used which then is disconnected when no longer needed (for v1.0.1).

As-well a bug i noticed that occurs sometimes randomly in v1.0.1 and v1.0.0 is it not disconnecting the HeartBeat connection which then causes weird issues with the slider, like on mobile, tapping on the left side of the screen even if not within the slider makes the slider go completely to 0 and such..

I recommend using full service names, instead of sometimes using UIS (which translates to UserInputService) and when creating code, make sure no var is unused.

Heres my modified version of the module (refer to my note at end of this reply):
UISlider adudu21 version of 1.0.1.rbxm

[spoiler]
By the way, maybe gamepad support could be made via virtual cursor (StarterGui)
[/spoiler]

Note: Im not saying its something you have to exactly use, its a modified version you can use to change some stuff! From my testing, what i wrote does not seem to error so i will use it for my stuff.

1 Like

Yes, it would be much easier to set it to nil. It was mainly a band-aid fix with what I said above.
I’ll add this to the next update I do with it.

Isn’t this similar to what is done with DragDetectors?

Possibly. I don’t have too much knowledge on UIDragDetectors, and they looked kinda complex. So this just simplifies it a bit.

I’m sure you can prob use UIDragDetectors for the same thing, but there are many convenience methods built-in to the class.

Have a look at them. Sometimes there is no scripting necessary, just the setup of the start point and the end point.

Is there a way to like lock the axis to a specific axis or smth?

I saw your editted message with the bug you mentioned:

I’m having trouble replicating this. Can you share a video please?

Ello there again, it seems like i dont have the exact issue anymore for some reason (it only happened to me 2 - 3 times when testing) however i do have a similar issue thats easy to replicate, which happens if the user taps somewhere on the screen while they are as-well hold-tapping the slider button:


(lower quality to fit the 10mb max devforum upload limit)

As-well, i noticed in v1.0.1 that OnSliderReleased is firing even if the slider was not released from a click which may not be wanted if its used to tell the server to save settings:

1 Like

Ahh I see. It’s because the InputEnded fires regardless of whether it was pressed before, and due to the fact its UserInputService.
I kinda applied a band-aid fix for v1.0.1, I’ll address a lot of these issues! Thanks for pointing these out, it helps a lot. :smiley:

1 Like

Did you read the documentation I linked? There are a couple links if you Search the create.roblox.com site for DragDetectors.

2 Likes

I’ve noticed that when the frame holding the slider visibility is set to false, you can still interact with the slider?

Is this a bug or something

I don’t think it’s a bug. You should still be able to interact with the slider, even if visibility is off. This might change in the future, I’m not sure if I’m going to continue to update it though.

The newest version of the model seems to still have this part broken:

local function setupConnectionsAndSignals(self: UISliderInternals)
	local sliderThumb = self.config.sliderThumbButton
	-- Connect to InputBegan of our thumb button
	connectToAndStoreConnection(self, UIS.InputBegan, function(...)
		onSliderThumbPressed(self, ...)
	end)
	-- Connect to InputEnded as well
	connectToAndStoreConnection(self, UIS.InputEnded, function(...)
		onSliderThumbReleased(self, ...)
	end)
end