SettingsModule v1.2 | Open-source, easy-to-use settings module

settingsmodule1

SettingsModule v1.2 [UPDATE!]


Introducing SettingsModule, an open-source module to assist you with creating settings in your game.

Notes

  • SettingsModule is designed to help beginner scripters add settings to their games. Although it’s got features for intermediate/advanced scripters too!

  • SettingsModule attempts to replicate Roblox API as closely as possible while also staying simple for beginners.

  • SettingsModule is meant for CLIENT-SIDE usage. Not recommended for use on the server.

Latest Update

API

Methods

Module

SettingsModule.new()
function SettingsModule.new(name: string, value: any)

Description: Creates a new setting. Returns the setting.

SettingsModule:WaitForSetting()
function SettingsModule:WaitForSetting(name: string, timeout: number)

Description: Returns a setting. If it doesn’t exist yet, it will continuously wait until it does and return it. If timeout is specified, it will wait for the setting until the timeout has completed, in which then it will throw a warning and return nothing.

SettingsModule:RetrieveSaveData()
function SettingsModule:RetrieveSaveData()

Description: Returns a JSON encoded string for data storage.
Note: This method will not save certain values, like objects. However it does have built-in conversion for the following data types:

  • Enums
SettingsModule:WriteSaveData()
function SettingsModule:WriteSaveData(save: string)

Description: JSON decodes a string returned from :RetrieveSaveData and sets the resulting table to the settings.
Note: Still has conversion methods listed in RetrieveSaveData().

Settings

Setting:Destroy()
function Setting:Destroy()

Description: Permanently destroys a setting. Not recoverable.

Setting:Set() (deprecated)
function Setting:Set(newValue: any)

Description: Sets a setting to a new value.
Deprecation: This method is deprecated, but included for backwards-compatibility. setting.Value = newValue is favored.

Setting:TweenSet()
function Setting:TweenSet(endValue: any, tweenInfo: TweenInfo)

Description: Will tween a setting to an end value with the provided TweenInfo.
Note: You can currently only tween the following data types:

  • Numbers
  • Booleans
  • CFrames
  • Color3s
  • Vector3s

Signals

Module

SettingsModule.SettingChanged
SettingsModule.SettingChanged:Connect(function(setting)

Description: Signal that fires whenever any setting is changed. Returns the setting.

SettingsModule.SettingAdded
SettingsModule.SettingAdded:Connect(function(setting)

Description: Signal that fires whenever any setting is added. Returns the setting.

SettingsModule.SettingRemoved
SettingsModule.SettingRemoved:Connect(function(setting)

Description: Signal that fires whenever any setting is removed. Returns the setting.

Settings

Setting.Changed
Setting.Changed:Connect(function(newValue)

Description: Signal that fires whenever the specific setting is changed. Returns its new value.

Setting.Removing
Setting.Changed:Connect(function(oldSetting)

Description: Signal that fires whenever the specific setting is destroyed. Returns itself before destruction.

Objects

Setting
SettingsModule.new(name: string, value: any)

Description: Setting object. Hierarchy and “properties” looks like this:

  • Module (dictionary)

    The module (technically classified as a dictionary).

    • Settings (dictionary)

      A dictionary containing all existing settings. You can access settings from this but it is recommended to use :WaitForSetting(name: string).

      • Setting (object)

        The Setting object. This is what is returned when you call :WaitForSetting(name: string), SettingsModule.new(name: string, value: any), etc.

        • Name (property)

          The name of the setting. Read-only.

        • Value (property)

          The value of the setting. Can be set.

        • Type (property)

          The datatype of the setting’s value. Read-only. Equivalent to using typeof(Setting.Value).

        • Changed (signal)

          A signal that fires whenever the setting’s value is changed.

        • Removing (signal)

          A signal that fires whenever the setting is about to be destroyed.

        • IsConverted (property, internal)

          A property used internally to convert objects such as Enums into savable data. Read-only. Under no circumstances should you change this property.

        • Destroy() (function)

          A function that permanently destroys the setting.

        • Set() (function)

          A function that sets the setting’s value.

        • "TweenSet() (function)

          A function that tweens the setting’s value to the specific goal value.

:warning: WARNING: All of these properties, except for .Value are READ-ONLY.

:warning: WARNING: Setting objects are NOT actual values or instances.

Tutorials

The Basics

The GUI and scripts located in this tutorial are in this free model: SettingsModule | The Basics - Roblox. It can also be found in the place: SettingsModule Tutorial - Roblox

For the basic settings, we will be creating three settings (that work):

  • Volume
  • Shadows
  • FOV

If you follow this tutorial correctly, these three settings will work without any further scripting needed. Now onto the tutorial.

  1. Create a ScreenGui in StarterGui. Design your settings screen to accommodate those three settings mentioned earlier. Make sure the names of objects are unique and make sense, and aren’t names like “TextButton3”.

My ScreenGui hierarchy looks like this:
image

  1. Create a LocalScript in the ScreenGui, as shown in the screenshot above. Inside it, write this script or something similar:
-- Get ReplicatedStorage as a service
local replicatedStorage = game:GetService("ReplicatedStorage")

-- Require SettingsModule so we can use it
local settingsModule = require(replicatedStorage:WaitForChild("SettingsModule"))

-- Create new settings
local volume = settingsModule.new("Volume", 0.5)
local shadows = settingsModule.new("Shadows", true)
local fov = settingsModule.new("FOV", 70)

-- Get all UI objects we need
local settingsGui = script.Parent
local background = settingsGui:WaitForChild("Background")

local volumeFrame = background:WaitForChild("Volume")
local shadowsFrame = background:WaitForChild("Shadows")
local fovFrame = background:WaitForChild("FOV")

local volumeInput = volumeFrame:WaitForChild("Input")
local shadowsToggle = shadowsFrame:WaitForChild("Toggle")
local fovInput = fovFrame:WaitForChild("Input")

-- Function for when the volume input changes
local function volumeChanged()
	-- Convert the input to a number
	local newVolume = tonumber(volumeInput.Text)
	
	-- Make sure that the new volume exists and isn't just nothing
	if newVolume then
		-- Make sure the volume isn't set to lower than 0 and higher than 1, set the new volume
		volume:Set(math.clamp(newVolume, 0, 1))
	end
end

-- Function for when the shadows button is clicked
local function shadowsChanged()
	-- If shadows are enabled, then...
	if shadows.Value == true then
		shadowsToggle.Text = "OFF" -- Set button text to OFF
		shadowsToggle.BackgroundColor3 = Color3.new(1, 0, 0) -- Set button color to red
		
		shadows:Set(false) -- Set the new value
	-- Else if shadows aren't enabled, then...
	else
		shadowsToggle.Text = "ON" -- Set button text to ON
		shadowsToggle.BackgroundColor3 = Color3.new(0, 2, 0) -- Set button color to green

		shadows:Set(true) -- Set the new value
	end
end

-- Function for when the FOV input changes
local function fovChanged()
	-- Convert the input to a number
	local newFov = tonumber(fovInput.Text)

	-- Make sure that the new FOV exists and isn't just nothing
	if newFov then
		-- Make sure the FOV isn't set to lower than 70 and higher than 120, set the new volume
		fov:Set(math.clamp(newFov, 70, 120))
	end
end

-- Connect the functions to the inputs
volumeInput:GetPropertyChangedSignal("Text"):Connect(volumeChanged)
shadowsToggle.Activated:Connect(shadowsChanged) -- Equivalent to clicking it, but works for mobile
fovInput:GetPropertyChangedSignal("Text"):Connect(fovChanged)

If you copy/paste my script, make sure that all the UI objects you reference are correct.

  1. Create a new LocalScript in StarterPlayer > StarterPlayerScripts. Inside it, write this or something similar:
-- Get the services we need
local replicatedStorage = game:GetService("ReplicatedStorage")
local lighting = game:GetService("Lighting")

-- Require SettingsModule so we can use it
local settingsModule = require(replicatedStorage:WaitForChild("SettingsModule"))

-- Get the player's camera
local camera = workspace.CurrentCamera

-- Wait for the settings to be created by the Handler script we created before
local volume = settingsModule:WaitForSetting("Volume")
local shadows = settingsModule:WaitForSetting("Shadows")
local fov = settingsModule:WaitForSetting("FOV")

-- Function for when the volume setting is changed
local function volumeChanged(newVolume)
	-- Loop through all instances in the game
	for _, instance in ipairs(game:GetDescendants()) do
		-- Check if the instance is a sound
		if instance:IsA("Sound") then
			-- Set the sound's volume to the new volume
			instance.Volume = newVolume
		end
	end
end

-- Function for when the shadows setting is changed
local function shadowsChanged(newShadows)
	-- Sets shadows to the new value
	lighting.GlobalShadows = newShadows
end

-- Function for when the FOV setting is changed
local function fovChanged(newFov)
	-- Set the camera's FOV to the new value
	camera.FieldOfView = newFov
end

-- Connect the functions to the settings' Changed signals
volume.Changed:Connect(volumeChanged)
shadows.Changed:Connect(shadowsChanged)
fov.Changed:Connect(fovChanged)

Technically, you could merge these two scripts together, but to show you how to access settings from other scripts, I split them in two.

  1. Test it!
    Test out the system. See if any errors or warnings show up in the console. If you can’t seem to get it working, reply to this thread or private message me so we can work it out.

Here’s video footage of my testing for comparison:

The Basics | SettingsModule - Google Drive

Hopefully, this tutorial helps you gain a better understanding of how this module works! The comments in the scripts should be enough for you to understand how they work, but if you have any more questions about it, just ask me.

Good luck!

Tweening

WIP

Data Saving

WIP

Keybinds

WIP

Resources

You can get the model here:

You can get the open-source tutorial place here:

You can get the .RBXM file here:
SettingsModule v1.1.rbxm (3.8 KB)

GitHub has been closed because I have no idea how to parent modules under modules. Sorry, Rojo users!

License

MIT License

MIT License

Copyright (c) 2023 Fizzitic/Fizzitix

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the “Software”), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

Read the full document here.

End

If you want, you can create your own variants of this module and release them under your name. The license says so.

Fizzitix

30 Likes

Does this have enum support? Because normally you cannot save enums but there is a way to get around it.
I was wondering if you have implemented this into your system. If not, I think that would be a great thing to add in a later update.
It would personally help me very very much for allowing players to change keybinds in a game I’m working on!
Either way this seems like a great module and I will most likely be using this! Thanks! :smiley:

2 Likes

Thanks! I will look into Enum support and will most likely add it in v1.1. Thanks for supporting my module

Edit as of 7/25/23:

v1.1 now supports saving Enums.

Fizzitix

1 Like

BUG NOTICE:
A bug has been discovered with the module. Do not use Module:EnableSaving() or Module:Save(). It will return an error and stop the module from working. This will be fixed as soon as possible.

Edit as of 7/25/23:
Saving fixed in v1.1. Methods such as :EnableSaving() and Module:Save() no longer exist.

Thanks for sticking with me,
Fizzitix

What does a setting module mean?

My SettingsModule allows you to create settings, check their values, check when a setting’s value changes, and much, much more. If this doesn’t answer your question, please follow up.

Edit as of 7/25/23:

SettingsModule now has many more features than this. Check out main post for more info.

Thanks,
Fizzitix

what do you exactly mean by a setting? Do you mean like an attribute?

1 Like

Like for example in Minecraft there are settings for stuff like FOV, Mouse sensitivity, volume, ect.

2 Likes

@Bitterman1021 described it perfectly, but there are some other features that are built-in to the module:

  • Autosaving(currently bugged, will fix ASAP)
  • Ability to use settings across multiple scripts
  • Ability to detect when a setting is changed

Of course, I have many more features in mind, such as:

  • Client-server replication
  • Built-in UI
  • Best optimization possible
    …and much, much more!

I hope this answered your question. If it didn’t, follow up again and I’ll get back to you.

Edit as of 7/25/23:

Listed items above with strikethrough lines are no longer relevant.

Thanks,
Fizzitix

3 Likes

Here is a graphics setting module you could use with this module, it comes with lots of features.

1 Like

You could! Perhaps you could create a setting that changes the game quality using the graphics module.
For example, if the setting is changed to 1, you could disable all the graphics options. But, if the setting is changed to 10, you could enable all of the graphics options.

Edit as of 7/25/23:
I plan to add this as a tutorial in the near future. Stay tuned!

Hope this helped,
Fizzitix

IMPORTANT NOTICE: I no longer have the time or resources to continue working on this module. I may restart in the future when I have time to do so. Autosaving is broken and does not currently have a fix. You may create your own variants of this module and release them separately if you’d like.

Edit as of 7/25/23:

Yes I do!

1 Like

SettingsModule v1.1 Update Log

That’s right, it’s back! With a complete rewrite of stinky old v1.0 that barely worked, I’ve got a buttload of new features and improvements to introduce to you.

Just a warning before we start…

:warning: WARNING: v1.1 is NOT backwards-compatible with v1.0 (stuff that worked with v1.0 no longer works with v1.1)! You will need to make drastic changes to upgrade (although its definitely worth it :wink:).

1. Signals

Instead of utilizing BindableEvents, SettingsModule now uses BetterSignal for easier connections and more features. Now you can use Connection:Wait(), Connection:Once(), and so much more!

Almost forgot to mention: I’ve added multiple new signals, such as SettingChanged, SettingAdded and SettingsRemoved. Each setting will have their own special signal that fires when that specific setting is changed.

2. Retrieve/Write Save Data

It’s been a while, and I’ve come to realize that saving data on the client with just one module is quite nearly impossible. So, I’ve introduced two new functions, :RetrieveSaveData and :WriteSaveData!
Both functions use JSON encoding to retrieve and write save data. Unfortunately, you will have to create your own DataStore script, but I plan to make a tutorial for that on the main post. (Now with support for Enums! @Bitterman1021 you’re welcome!)

3. Setting System

Didn’t quite know what to call this section. Anyways, the way settings and created, changed, and removed have been vastly modified.

Setting hierarchy now looks like this:

  • Module (dictionary)
    • Settings (dictionary)
      • Index (key)
        • Name (property)
        • Value (property)
        • Type (property)
        • Changed (signal)
        • IsConverted (INTERNAL property, DO NOT CHANGE!!!)
        • Destroy() (function)
        • Set() (function)
        • TweenSet() (function)

:warning: WARNING: All of these properties are READ-ONLY. (ESPECIALLY ISCONVERTED. WHATEVER YOU DO, DO NOT MESS WITH ISCONVERTED).

Create a setting with:

module.new(name: string, value: any)

Set a setting with:

setting:Set(newValue: any)

:warning: WARNING: Attempting to change a setting’s value with module.Settings.SETTINGNAME.Value will not fire Changed signals. Please use setting:Set() instead.

Get a setting with:

module:WaitForSetting(name: string) (recommended)

OR…

module.Settings.SETTINGNAME (unrecommended and unreliable)

Destroy a setting with:

setting:Destroy()

And finally, last but not least…
A new and fun feature

Tween a setting with:
setting:TweenSet(endValue: any, tweenInfo: TweenInfo)

There’s a lot more to settings that will be in the documentation, so check that out!

Conclusion

That’s mostly everything for v1.1. If you have any more questions, feel free to ask me in DMs or this thread.

Future Plans

  • Default UI with basic settings (volume, shadows, etc.)
  • Data saving tutorial (with free scripts)
  • Version system
1 Like

:mega: “The Basics” tutorial is out! :mega:

I’ve just finished “The Basics” tutorial, which offers three working settings, GUI, etc, for free.

Along with this, I will be publishing the tutorial place again, which will contain this tutorial.

Best of luck!
Fizzitix

2 Likes

SettingsModule v1.2 Update Log

:information_source: NOTICE: v1.2 is backwards-compatible with v1.1, although some features endorsed in v1.1 are now deprecated.

The third installment of SettingsModule makes use of metatables and metamethods to make some properties read-only and others able to be edited.

1. Direct value indexing

You are now able to set the value of a setting using setting.Value. This allows for the use of compound operators such as += and -= to make your scripting experience a little easier.
setting:Set() will remain as a function, however it is now deprecated and is planned to be fully removed in future versions.

2. Removing signal

Each setting now has a Removing signal that fires before the setting is destroyed using setting:Destroy().
It returns the setting that is being removed just in case it is destroyed before you can take action.

3. WaitForSetting() improvements

SettingsModule:WaitForSetting() has been improved internally and now relies on the SettingAdded signal instead of repeat task.wait() until.
It also has an extra, optional parameter: timeout. If the setting does not exist and the module has been waiting for it to appear for longer than the specified timeout, it will produce a warning and return nothing.

As an added note: Attempting to access the SettingsModule metatable will return "This metatable is locked". This is to prevent any modifications that might result in the module not working as intended.

Conclusion

That’s mostly everything for v1.2. If you have any more questions, feel free to ask me in DMs or this thread.

Future Plans

  • Ability to modify settings’ names
  • General optimization
  • Metatable improvements (I am just beginning to learn about metatables)
  • Use of userdata instead of normal tables for proxies

When are you planning to release the data saving tutorial?

Honestly, if you guys want it, I can make it as soon as tomorrow. Even before the tweening tutorial.

2 Likes

I just implemented your module yesterday instead of my spaghetti code and I would love to be able to implement data stores since my datastore code kept saying I sent too many requests(it only saved once the player left or the server was closing) and didn’t work. I’ll be waiting for the tutorial but take your time and make it whenever you want.

2 Likes

Any updates on when the datastore tutorial will be released?

1 Like