I want to create options so the player can toggle between them (Disable textures, disable gun sounds, etc) but i have no almost no idea what is the best way to create them.
So far i have done some research on the forum and i found a post (I was going to link it but i didn´t found it) where it says that i should have a folder on each player with BoolValues or StringValues that represent each option and then toggle them with a RemoteEvent when the player presses a button on my settings Gui
Example:
local Players = game:GetService("Players")
Players.PlayerAdded:Connect(function(plr)
local plrSettings = Instance.new("Folder")
plrSettings.Name = "PlrSettings"
plrSettings.Parent = plr
local textureToggle = Instance.new("BoolValue")
textureToggle.Name = "TextureToggle"
textureToggle.Parent = plrSettings
local shadowToggle = Instance.new("BoolValue")
shadowToggle.Name = "ShadowToggle"
shadowToggle.Parent = plrSettings
local muteGunSound = Instance.new("BoolValue")
muteGunSound.Name = "MuteGunSound"
muteGunSound.Parent = plrSettings
local disableUsername = Instance.new("BoolValue")
disableUsername.Name = "DisableUserName"
disableUsername.Parent = plrSettings
end)
Then i should store all of the values on a DataStore, but im not to sure on how to do that.
Is this the best way of creating options? Or there are better ways to do this?
(Also sorry if i made some grammar mistakes, English is not my main languaje)
Using tables and datastoreservice would be your best move here, unless your consistently and regularly updating the settings (which I wouldn’t assume you are).
I’ll leave some example code below;
local PlayerService = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
local SettingsDataStore = DataStoreService:GetDataStore("settings_storage") -- or whatever you would like the key to be, doesn't matter
--[[
use :GetAsync & UpdateAsync to update player data
]]--
--[[
Your table would be structured how you like, but I would do it as the same names:
]]
local base_user_settings = {
textureToggle = false,
shadowToggle = false,
muteGunSound = false,
disableUserName = false
}
PlayerService.PlayerAdded:Connect(function(player)
local success, response = pcall(function()
return SettingsDataStore:GetAsync(player.UserId)
end)
if not success then -- did the data store error
warn(response)
end
if not response then -- if no values are currently stored then set it to your default settings
response = base_user_settings
end
playerdata = response
--[[
to access these values, you can use either or below:
playerdata["setting_name"]
or
playerdata.setting_name
]]
--your code/changes you need to make to settings or just loading them
-- once ur done, if you make any changes store it like this:
local success, response = pcall(function()
return SettingsDataStore:SetAsync(player.UserId, playerdata)
end)
if not success then
warn(response)
end
end)
--[[
note: pcall function just catches the error and doesnt allow it to stop your script from running
For now the texture changes for everyone becouse i have no idea on how i should do it only for the client, but that´s not a big problem, i think i kinda figured it out.
The biggest problem it that it doesent saves the player values, when i enter and i disable the textures and then i leave, when i come back all the textures are enabled, idk what is the problem, if you could provide some help it would be great.
Script:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
local DataStore = game:GetService("DataStoreService")
local settingsEvent = ReplicatedStorage.RemoteEvents.SettingsEvent
local plrModule = require(script.PlayerModule)
local settingsDataStore = DataStore:GetDataStore("plrsettings")
local sessionData = {}
--Base data
local usersettings = {
textureToggle = false,
shadowToggle = false,
muteGunsound = false,
disableUsername = false
}
Players.PlayerAdded:Connect(function(player)
local success = nil
local plrData = nil
local attemp = 1
--We are going to try to get the data 5 times in case it failed
repeat
success, plrData = pcall(function()
return settingsDataStore:GetAsync(player.UserId)
end)
attemp += 1
if not success then
warn(plrData)
task.wait(2)
end
until success or attemp == 5
--If there is not player data we are going to set the base one which is usersettings
if not plrData then
plrData = usersettings
end
--If there is no success we are going to kick the player
if success then
print("DataStore works!")
sessionData[player.UserId] = plrData
else
player:Kick("Unable to get your settings data! if the error persists report to the dev team inmediatly")
end
end)
--We are adding another function for when the player leaves
function plrIsLeaving(player)
if sessionData[player.UserId] then
local success = nil
local errorMsg = nil
local attemp = 1
repeat
success, errorMsg = pcall(function()
settingsDataStore:SetAsync(player.UserId, sessionData[player.UserId])
end)
attemp += 1
if not success then
warn(errorMsg)
task.wait(2)
end
until success or attemp == 5
if success then
print("Data saved!")
else
warn("Unable to save settings")
end
end
end
Players.PlayerRemoving:Connect(plrIsLeaving)
--Another function in case of server shutdown
function serverShutdown()
if RunService:IsStudio() then
return
end
for i, player in pairs(Players:GetPlayers()) do
task.spawn(function()
plrIsLeaving(player)
end)
end
end
game:BindToClose(serverShutdown)
settingsEvent.OnServerEvent:Connect(function(plr, name)
if name == "TexturesFrame" then
local textureData = sessionData["textureToggle"]
sessionData["textureToggle"] = not sessionData["textureToggle"]
plrModule:TextureToggle(textureData)
end
end)
Players.PlayerAdded:Connect(function()
local textureData = sessionData["textureToggle"]
plrModule:TextureToggle(textureData)
end)
LocalScript:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local gui = script.Parent
local buttonSettings = gui.OpenButton
local settingsFrame = gui.SettingsFrame
local scrollingFrame = settingsFrame.ScrollingFrame
local settingsEvent = ReplicatedStorage.RemoteEvents.SettingsEvent
buttonSettings.MouseButton1Click:Connect(function()
settingsFrame.Visible = not settingsFrame.Visible
end)
for i, v in pairs(scrollingFrame:GetChildren()) do
if v:IsA("Frame") then
local button = v:FindFirstChild("ImageButton")
local name = v.Name
button.MouseButton1Click:Connect(function()
settingsEvent:FireServer(name)
end)
end
end
Players.PlayerAdded:Connect(function()
local textureData = sessionData["textureToggle"]
plrModule:TextureToggle(textureData)
end)
Firstly you need sessionData[plr.UserID] to get the players settings. Right now you are trying to get a player userID “textureToggle”.
Secondly you are trying to pass a boolean into :TextureToggle(textureData) the problem is that this will pass a copy to that so the update will never be seen here (only tables are shared when passed). Instead do sessionData[plr.UserID][“textureToggle”] = not sessionData[plr.UserID][“textureToggle”] which does a toggle.
As for this, anything you do on the server effects every client, anything you do in a client script for the most part only affects the client (there are some exceptions). So you simply need to have the server send back to the client whether they should enable or disable textures and let the client do that. The client needs this anyways when you load the data otherwise your UI won’t be synced with the data from the server and will act like there is no data.