I am making an April Fools event for my game, and I am using DataStore to store how many chapters the player has completed. However, the data is always nil. Is there a fix to this?
local Players = game:GetService("Players")
local Ds = game:GetService("DataStoreService")
Players.PlayerAdded:Connect(function(player)
--check if there is already a leaderstats folder. if not, create a new one.
local leaderstats = player:FindFirstChild("leaderstats")
if leaderstats then
leaderstats = player.leaderstats
else
leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
end
local chapters = Instance.new("IntValue")
chapters.Name = "Completed"
--load data
local dataStore
local data
local success, errorMessage = pcall(function()
dataStore = Ds:GetDataStore("ChaptersCompleted")
data = dataStore:GetAsync(player.Name)
end)
if success then
print("Loaded data successfully.")
else
warn("Failed to load data "..errorMessage..". If you see this error, please report this bug to the group wall immediately.")
end
chapters.Value = data
chapters.Parent = leaderstats
end)
Are you saving the data somewhere? If so, please provide that code as well
Also, you should be using :GetAsync(player.UserId), rather than :GetAsync(player.Name), as the player’s name may be changed at some point in which case they would lose all their data with your current code
local part = script.Parent
local TpService = game:GetService("TeleportService")
local DataStoreService = game:GetService("DataStoreService")
local PLACE_ID = 131839010607565
local debounce = false
local dataStore = DataStoreService:GetDataStore("ChaptersCompleted", "Chapters in the event")
local function onTouch(hit)
if debounce then return end
local parent = hit.Parent
local humanoid = parent:FindFirstChild("Humanoid")
if humanoid then
local player = game.Players:GetPlayerFromCharacter(parent)
if player then
debounce = true
local leaderstats = player.leaderstats.Completed
leaderstats.Value = 1
local success, errorMessage = pcall(function()
--save game
dataStore:SetAsync(tostring(player.UserId), 1)
--teleport player.
TpService:Teleport(PLACE_ID, player)
end)
if success then
print("Save and teleport successful.")
else
warn("Failed to teleport player: "..errorMessage..". If you are a player, please report this bug to the group wall immediately. (Group linked in description).")
end
task.wait(5)
debounce = false
end
end
end
part.Touched:Connect(onTouch)
yeah, but thats the problem
see if you add the userid as a string into the datastore, it will only be seen as a string
simplified version
“123” ~= 123
because 123 is a number, and “123” is a string, they are not equal
tostring(player.UserId) ~= player.UserId
so if you plug in “123” into the datastore, and try gathering that data stored using 123, the script doesn’t recognize 123 as “123”, so it returns nil.
This is happening because while you are getting the right data store, you’re getting a different scope. Notice how your dataStore local variable in the code where the data is saved is:
local dataStore = DataStoreService:GetDataStore("ChaptersCompleted", "Chapters in the event")
But when retrieving the datastore for loading the data, this scope isn’t specified:
local success, errorMessage = pcall(function()
dataStore = Ds:GetDataStore("ChaptersCompleted") -- missing scope here
data = dataStore:GetAsync(player.Name)
end)
So two fixes; either remove the unnecessary scope so that it just saves to ChaptersCompleted, or you actually add the scope.
The reason why the data it returns is nil is because there is no data in the default scope for ChaptersCompleted, but there is for "Chapters in the event". Datastore scopes matter.
The fix is as simple as this:
local success, errorMessage = pcall(function()
dataStore = Ds:GetDataStore("ChaptersCompleted", "Chapters in the event") -- added scope as 2nd argument
data = dataStore:GetAsync(player.Name)
end)