I have made a data store script with added print statements.
the data the saves is a boolean value
When I made the boolean value to false (its through the serverside), and leave the game it prints that the boolean value is false
But when I rejoin it prints that the boolean value is true.
Any solutions?
local DS = game:GetService("DataStoreService")
local player_data = DS:GetDataStore("TutorialTest")
local function savePlayerData(player)
if not player or not player.Parent then return end -- Ensure player exists
local success, errorMessage = pcall(function()
player_data:SetAsync(player.UserId, player.TutorialEnabled.Value)
end)
if not success then
warn("Failed to save data for player " .. player.Name .. ": " .. errorMessage)
else
print("Successfully saved data for player: ", player.Name)
end
end
local function loadPlayerData(player)
local success, data = pcall(function()
return player_data:GetAsync(player.UserId)
end)
if success and data then
print("Successfully loaded data: ", data)
player.TutorialEnabled.Value = data
else
print("Data loading failed or no data found. Setting default value to true.")
player.TutorialEnabled.Value = false
end
end
game.Players.PlayerAdded:Connect(function(player)
local TutEnable = Instance.new("BoolValue")
TutEnable.Name = "TutorialEnabled"
TutEnable.Parent = player
print("Player added: ", player.Name)
print("Loading data for UserId: ", player.UserId)
loadPlayerData(player)
print("Loaded TutorialEnabled Value: ", player.TutorialEnabled.Value)
end)
game.Players.PlayerRemoving:Connect(function(player)
print("Player removing: ", player.Name)
print("TutorialEnabled Value Before Save: ", player.TutorialEnabled.Value)
savePlayerData(player)
end)
Roblox data stores treat nil and false the same when retrieving data with GetAsync() . If you store false, when you retrieve the value, the DataStore might return nil, making it seem like true (since your default is true).
This means the issue isn’t with saving but with retrieving false values correctly.
if this doesn’t work let me know
local DS = game:GetService("DataStoreService")
local player_data = DS:GetDataStore("TutorialTest")
local function savePlayerData(player)
if not player or not player.Parent then return end
local tutorialValue = player:GetAttribute("TutorialEnabled")
print("Saving TutorialEnabled:", tutorialValue)
local success, errorMessage = pcall(function()
player_data:SetAsync(player.UserId, tutorialValue)
end)
if not success then
warn("Failed to save data for", player.Name, ":", errorMessage)
else
print("Successfully saved data for", player.Name)
end
end
local function loadPlayerData(player)
local success, data = pcall(function()
return player_data:GetAsync(player.UserId)
end)
if success then
print("Loaded data:", data)
if data ~= nil then
player:SetAttribute("TutorialEnabled", data)
else
print("Data was nil, setting default value to false.")
player:SetAttribute("TutorialEnabled", false)
end
else
warn("Failed to load data for", player.Name)
player:SetAttribute("TutorialEnabled", false)
end
end
game.Players.PlayerAdded:Connect(function(player)
print("Player joined:", player.Name)
loadPlayerData(player)
print("Final TutorialEnabled Value:", player:GetAttribute("TutorialEnabled"))
end)
game.Players.PlayerRemoving:Connect(function(player)
print("Player leaving:", player.Name)
print("TutorialEnabled before saving:", player:GetAttribute("TutorialEnabled"))
savePlayerData(player)
end)
if data will only proceed to the subsequent code if data is a value that isn’t nil nor false. If you want to narrow it down to check if it’s nil (and subsequently apply the default value), then you should do if data ~= nil
Even with that the boolean value still loads as true when it saves as false.
local DS = game:GetService("DataStoreService")
local player_data = DS:GetDataStore("TutorialTest")
local function savePlayerData(player)
if not player or not player.Parent then return end -- Ensure player exists
local success, errorMessage = pcall(function()
player_data:SetAsync(player.UserId, player.TutorialEnabled.Value)
end)
if not success then
warn("Failed to save data for player " .. player.Name .. ": " .. errorMessage)
else
print("Successfully saved data for player: ", player.Name)
end
end
local function loadPlayerData(player)
local success, data = pcall(function()
return player_data:GetAsync(player.UserId)
end)
if success and data ~= nil then
print("Successfully loaded data: ", data)
player.TutorialEnabled.Value = data
else
print("Data loading failed or no data found. Setting default value to true.")
player.TutorialEnabled.Value = true
end
end
game.Players.PlayerAdded:Connect(function(player)
local TutEnable = Instance.new("BoolValue")
TutEnable.Name = "TutorialEnabled"
TutEnable.Parent = player
print("Player added: ", player.Name)
print("Loading data for UserId: ", player.UserId)
loadPlayerData(player)
print("Loaded TutorialEnabled Value: ", player.TutorialEnabled.Value)
end)
game.Players.PlayerRemoving:Connect(function(player)
print("Player removing: ", player.Name)
print("TutorialEnabled Value Before Save: ", player.TutorialEnabled.Value)
savePlayerData(player)
end)
While the documentation clearly states “This event fires before ChildRemoved does on Players, and behaves somewhat similarly to Instance.DescendantRemoving. Since it fires before the actual removal of a Player”
This statement proves to be false when SignalBehavior is set as “Deferred” under the workspace, as signals fire on the next resumption point when this mode is set.
There was a Roblox announcement claiming “SignalBehavior may improve performance in some experiences” this feature has since been turned on by default in all experiences.
You can either turn this off under your Workspace’s properties tab or just remove the guard clause.