How can I make saving settings?

  1. I would like to have settings that save when the player joins and that also save on to different places within the experience

  2. I tried some articles but none of them really helped because they didn’t go into too much detail. I tried searching stuff on youtube that also didn’t work.

I would like to know how I can make datastore to store settings so I can put them onto a different place and so they can save. I have a rough idea on how to do it but unfortunately, I don’t have the skills nor the intelligence to pull it off.

2 Likes

I’d personally do it by having a default data table for when a player first joins. When a player edits their settings, update their local setting table (cached data), and when they leave, save this local data table to a data store. This approach limits set/update/get requests very well if you ask me

1 Like

How could I achieve such things?

I understood as you are asking “how can i achieve more settings than the limit?”. (sorry if my english is bad im a turkish developer.)

If i understand correclty, You can use the Profile Service to save multiple things.Even you have such things.

If i understood you uncorrectly, Can you describe what you’re doing simply? So i can help you fix your problem.

I want to make a saving settings datastore. But whatever I am trying isn’t working it gives me errors like dictionary isn’t supported. here is my code:

local DataStoreService = game:GetService("DataStoreService")
local SettingsDataStore = DataStoreService:GetDataStore("PlayerGraphicsSettings")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

-- Default settings
local defaultSettings = {
	Atmosphere = true,
	Bloom = true,
	Blur = true,
	Diffuse = true,
	Reflections = true,
	Shadows = true,
	Sunrays = true,
	WaterWaveSize = 0.15, -- Default wave size
	WaterWaveSpeed = 10,  -- Default wave speed
}

-- Function to load settings for a player
local function loadSettings(player)
	local key = "Settings_" .. player.UserId
	local success, data = pcall(function()
		return SettingsDataStore:GetAsync(key)
	end)
	if success and data then
		return data
	else
		return defaultSettings
	end
end

-- Function to save settings for a player
local function saveSettings(player, settings)
	local key = "Settings_" .. player.UserId
	local success, errorMessage = pcall(function()
		SettingsDataStore:SetAsync(key, settings)
	end)
	if not success then
		warn("Failed to save settings for " .. player.Name .. ": " .. errorMessage)
	end
end

-- Function to apply settings to the environment
local function applySettings(settings)
	if settings.Atmosphere ~= nil then
		if settings.Atmosphere then
			-- Enable atmosphere
			game.Lighting.Atmosphere.Parent = game.Lighting
		else
			-- Disable atmosphere
			game.Lighting.Atmosphere.Parent = ReplicatedStorage
		end
	end

	if settings.Sunrays ~= nil then
		if settings.Sunrays then
			-- Enable sunrays
			ReplicatedStorage.SunRays.Parent = game.Lighting
		else
			-- Disable sunrays
			game.Lighting.SunRays.Parent = ReplicatedStorage
		end
	end
	
	if settings.Shadows ~= nil then
		if settings.Shadows then
			game.Lighting.GlobalShadows.Parent = game.Lighting
		else
			game.Lighting.GlobalShadows.Parent = ReplicatedStorage
		end
	end
	
	if settings.Reflections ~= nil then
		if settings.Reflections then
			ReplicatedStorage.EnvironmentSpecularScale.Parent = game.Lighting
		else
			game.Lighting.EnvironmentSpecularScale.Parent = ReplicatedStorage
		end
	end
	
	if settings.Diffuse ~= nil then
		if settings.Reflections then
			ReplicatedStorage.EnvironmentDiffuseScale.Parent = game.Lighting
		else
			game.Lighting.EnvironmentDiffuseScale.Parent = ReplicatedStorage
		end
	end
	
	if settings.Blur ~= nil then
		if settings.Blur then
			ReplicatedStorage.Blur.Parent = game.Lighting
			ReplicatedStorage.DepthOfField.Parent = game.Lighting
		else
			game.Lighting.Blur.Parent = ReplicatedStorage
			game.Lighting.DepthOfField.Parent = ReplicatedStorage
		end
	end
	
	if settings.Bloom ~= nil then
		if settings.Bloom then
			ReplicatedStorage.Bloom.Parent = game.Lighting
		else
			game.Lighting.Bloom.Parent = ReplicatedStorage
		end
	end
	
	if settings.WaterWaveSize ~= nil and settings.WaterWaveSpeed ~= nil then
		workspace.Terrain.WaterWaveSize = settings.WaterWaveSize
		workspace.Terrain.WaterWaveSpeed = settings.WaterWaveSpeed
	end
end
	

	-- Repeat similar logic for other settings (Bloom, Blur, etc.)
	-- Example:
	-- if settings.Bloom ~= nil then
	--     if settings.Bloom then
	--         ReplicatedStorage.Bloom.Parent = game.Lighting
	--     else
	--         game.Lighting.Bloom.Parent = ReplicatedStorage
	--     end
	-- end

-- Handle player joining
game.Players.PlayerAdded:Connect(function(player)
	-- Load the player's settings
	local settings = loadSettings(player)
	player:SetAttribute("GraphicsSettings")

	-- Apply settings to the environment
	applySettings(settings)
end)

-- Handle player leaving
game.Players.PlayerRemoving:Connect(function(player)
	-- Save the player's settings
	local settings = player:GetAttribute("GraphicsSettings")
	if settings then
		saveSettings(player, settings)
	end
end)

here is the code for one of my settings’ toggle

local on = true
local rep = game:GetService("ReplicatedStorage")
local player = game.Players.LocalPlayer

script.Parent.MouseButton1Click:Connect(function()
	if on then
		on = false
		script.Parent.Parent.TextLabel.Text = "OFF"
		game.Lighting.SunRays.Parent = rep
	else
		on = true
		script.Parent.Parent.TextLabel.Text = "ON"
		rep.SunRays.Parent = game.Lighting
	end

	-- Update the player's settings
	local settings = player:GetAttribute("GraphicsSettings") or {}
	settings["Sunrays"] = on -- Adjust "Sunrays" to the corresponding setting
	player:SetAttribute("GraphicsSettings", settings)
end)

here are some of the errors i have gotten:
SunRays is not a valid member of ReplicatedStorage “ReplicatedStorage”

Players.RealAquzR.PlayerGui.MenuScreen.Stats.SettingsFrame.ScrollingFrame.MainFrame.Diffuse.Frame.TextButton.LocalScript:9: attempt to index number with ‘Parent’

Players.RealAquzR.PlayerGui.MenuScreen.Stats.SettingsFrame.ScrollingFrame.MainFrame.Shadows.Frame.TextButton.LocalScript:15: attempt to index nil with ‘GetAttribute’

Dictionary is not a supported attribute type

please help

You just can set the Enabled boolean to enable, or disable it.

If your Sunrays is not in Lighting, You will get this error.

You might trying to get attribute of a “nil” object.

I think you are trying to set table as attribute, But that’s not supported on studio.

My sunrays are in lighting and it is giving me that error

would it work better if instead of moving them to replicated storage i instead do something like

local on = true
local rep = game:GetService("ReplicatedStorage")
local player = game.Players.LocalPlayer

script.Parent.MouseButton1Click:Connect(function()
	if on then
		on = false
		script.Parent.Parent.TextLabel.Text = "OFF"
		game.Lighting.SunRays.Enabled = false
	else
		on = true
		script.Parent.Parent.TextLabel.Text = "ON"
		game.Lighting.SunRays.Enabled = true
	end

	-- Update the player's settings
	local settings = player:GetAttribute("GraphicsSettings") or {}
	settings["Sunrays"] = on -- Adjust "Sunrays" to the corresponding setting
	player:SetAttribute("GraphicsSettings", settings)
end)

could I do that or it still won’t work?

oh yeah and by the way settings won’t save either

Here is a tip for you.

You can have a two scripts. One of them Server, and one of them are client.

The client script will update player’s settings when it is changed by player. Then the client will send the server a table every settings and their values.

Then the server will receive it and update it to player’s DataStore.

For an example:
CLIENT

local Settings = script.Parent.Settings --> Configuration Instance

local SunRays= script.Parent.SunRays --> The SunRays button
local Blur = script.Parent.Blur --> The Blur button

local Remote = script.Parent.SaveSettings

SunRays.Activated:Connect(function() --> trigger the SunRays button
    if Settings and Settings:FindFirstChild("SunRays") then --> Does SunRays exist?
        Settings.SunRays.Value = not Settings.SunRays.Value --> Boolean value for SunRays
        if game:GetService("Lighting"):FindFirstChild("SunRays") then
            game:GetService("Lighting").SunRays.Enabled = Settings.SunRays.Value
            Remote:FireServer(Settings:GetChildren())
        end
    end
end)


Blur.Activated:Connect(function() --> trigger the Blur button
    if Settings and Settings:FindFirstChild("Blur") then --> Does Blur exist?
        Settings.Blur.Value = not Settings.Blur.Value --> Boolean value for Blur
        if game:GetService("Lighting"):FindFirstChild("Blur") then
            game:GetService("Lighting").Blur.Enabled = Settings.Blur.Value
            Remote:FireServer(Settings:GetChildren())
        end
    end
end)

so would this go in what like in the gui or in the server script service?

1 Like

This script was an example. not for your save script.

ahhh i see… I have a question… Is there a way easier way to do this because I am not even joking, I have been working on this nonstop for about 7 hours now…

Do you want an example that you can expand? I can offer that instead of a full system for you because I dont believe in spoon feeding

sure you can give me an example

or if you really wanted to you could spoon feed me if you really really wanted to

You need to encode the data as a JSON when saving and decode the JSON when loading, because dictionaries can’t be saved.

Sorry for the long wait. I was doing something else, but I made something that should work. I quickly ran through everything (3 minutes), so you should double-check the code to see if there are any data-saving issues.

Server:

--!strict
local Players = game:GetService("Players")
local DSS = game:GetService("DataStoreService")
local RS = game:GetService("ReplicatedStorage")

local Ds = DSS:GetDataStore("PlayerGraphicsSettings")

local defaultSettings = {
	Atmosphere = true,
	Bloom = true,
	Blur = true,
	Diffuse = true,
	Reflections = true,
	Shadows = true,
	Sunrays = true,
	WaterWaveSize = 0.15,
	WaterWaveSpeed = 10,  
}

local CachedData = {}

local Transmitter = RS.RemoteEvent --Example remote event location

local function GetandSetData(Player:Player, Saving:boolean, Info:any?)
	local Tries = 0
	local Max = 3

	local Sucess, Data = nil

	local ID = `{Player.UserId}`

	repeat
		Tries += 1

		Sucess, Data = pcall(Saving and Ds.SetAsync or Ds.GetAsync, Ds, ID, Info)

		if not Sucess and Data then warn(Data) end

		task.wait(1)
	until Sucess or Tries == Max
	
	return if Saving then nil else Data
end

local function OnJoin(Player:Player)
	local Data = GetandSetData(Player, false, nil)
	
	Data = Data or defaultSettings
	
	CachedData[Player.UserId] = Data
	
	Transmitter:FireClient(Player, Data)
end

local function OnLeave(Player:Player)
	local PlayerData = CachedData[Player.UserId]
	
	if not PlayerData then return end
	
	GetandSetData(Player, true, PlayerData)
	
	PlayerData = nil
end

local function SaveNewData(Player:Player, NewData:any)
	if not Player or not NewData or typeof(NewData) ~= "table" then return end
	
	CachedData[Player.UserId] = NewData
end

for _, Player in Players:GetPlayers() do
	OnJoin(Player)
end

Transmitter.OnServerEvent:Connect(SaveNewData)
Players.PlayerAdded:Connect(OnJoin)
Players.PlayerRemoving:Connect(OnLeave)

Client:

local RS = game:GetService("ReplicatedStorage")

local Remote = RS:WaitForChild("RemoteEvent")

Remote.OnClientEvent:Connect(function(Settings: any) 
	--Do something with the settings here...
end)

--Mock example of the client changing some settings 
repeat
	task.wait(10)
	
	Remote:FireServer({
		Atmosphere = true,
		Bloom = true,
		Blur = true,
		Diffuse = true,
		Reflections = true,
		Shadows = true,
		Sunrays = true,
		WaterWaveSize = 0.15,
		WaterWaveSpeed = math.random(1,10), 
	})
until false

If you have questions, please ask :smile:

Hey did you have solved it? I’m just wondering.