I’ve recently made a XP system but every time that I leave and rejoin back it always resets my level to 2 even though I may be a level 50.
This is the script for the server script as the other local scripts in the GUI just use the data and do everything but this is where I store and save all the data
local level = 1
local exp = 0
local axp = 20
local InStudio = game:GetService("RunService"):IsStudio()
if not InStudio then
level = game:GetService("DataStoreService"):GetDataStore("Levels")
exp = game:GetService("DataStoreService"):GetDataStore("EXP")
axp = game:GetService("DataStoreService"):GetDataStore("AXP")
end
function savedata(dataname, playerid, value)
if InStudio then return end
dataname:SetAsync(playerid, value)
end
game.Players.PlayerAdded:connect(function(player)
local levelz = Instance.new("IntValue")
levelz.Name = "Level"
local xpz = Instance.new("NumberValue")
xpz.Name = "Exp"
local xpn = Instance.new("IntValue")
xpn.Name = "ExpNeeded"
xpn.Parent = player
xpz.Parent = player
levelz.Parent = player
if not InStudio then
xpn.Value = axp:GetAsync(tostring(player.userId)) or 20
xpz.Value = exp:GetAsync(tostring(player.userId)) or 0
levelz.Value = level:GetAsync(tostring(player.userId)) or 1
else
xpn.Value = axp
xpz.Value = exp
levelz.Value = level
end
xpz.Changed:connect(function()
if player:WaitForChild("Exp").Value >=player:WaitForChild("ExpNeeded").Value then
levelz.Value = levelz.Value + 1
xpn.Value = math.floor(xpn.Value * 2)
xpz.Value = 0
savedata(level, player.userId, levelz.Value)
savedata(exp, player.userId, xpz.Value)
savedata(axp, player.userId, xpn.Value)
else
savedata(level, player.userId, levelz.Value)
savedata(exp, player.userId, xpz.Value)
savedata(axp, player.userId, xpn.Value)
end
savedata(level, player.userId, levelz.Value)
savedata(exp, player.userId, xpz.Value)
savedata(axp, player.userId, xpn.Value)
end)
end)
game.Players.PlayerRemoving:connect(function(player)
savedata(level, player.userId, player.Level.Value)
savedata(exp, player.userId, player.Exp.Value)
savedata(axp, player.userId, player.ExpNeeded.Value)
end)
A likely cause to your issue could be that you are hitting your data store limits causing your data store to throttle then making your data not save. This can been seen in your xpz.Changed function because you are saving data whenever it changes and not taking into account data store limits. This can be extremely hazardous because your Values could change very quickly.
Another, seemingly unlikely, cause to your problem could be that you are updating your Values client sided causing the server not to register the changes because of FilteringEnabled. Instead you should always handle any changes to data on the server that way the server will then pick up the changes.
Better Practices
It looks like you are only using SetAsync() to updates players data. This can be very hazardous because SetAsync() forces a save on that key without taking into account the previous value. Then also the Developers Hub advises against using SetAsync() for the exact reasons I just explained. Instead, the advised way to update data is by using UpdateAsync().
Another thing that you should be doing is wrapping all your data store calls in a pcall because they sometimes fail. Using pcall will allow you to catch the error.
Last but not least you shouldn’t be saving the players data when they leave the game without first checking if their data has been loaded. The reason why this causes data loss is because the player could leave before their data has been loaded causing their data to be overridden.
The general rule is to always use UpdateAsync() instead of SetAsync() when saving your data because SetAsync() can be hazardous. However there are some developers that use SetAsync() to save there data. DataStore2 is a great example of this and I think the reason why it does this is because it is never overriding and previous saved data. I will need some clarification on that though.
SetAsync() doesn’t take into account any previous saved data and should only be used when you need to force data. From my understanding it is fine to use SetAsync() when you don’t have any saved data for the player because you are not overriding any previous saved data.
You can use UpdateAsync() even when you don’t have any saved data. This is because it returns the current saved value and then you can check if the current value is nil and then return default data. Here is a tuturial on why you should be using UpdateAsync: Stop using SetAsync() to save player data. Then here is some horrible code that I just made to show how you can use UpdateAsync() even when you don’t have any saved data:
local DataStoreService = game:GetService("DataStoreService")
local DataStore = DataStoreService:GetDataStore("Test")
local DefultValue = 20
game.Players.PlayerAdded:Connect(function(Player)
local Success, Error = pcall(function()
DataStore:UpdateAsync(tostring(Player.UserId), function(CurrentValue)
if CurrentValue == nil then
print("No data exists")
return DefultValue
else
print("Data Exists")
return CurrentValue + 4
end
end)
end)
if not Success then
warn(Error)
end
end)
Please don’t use this code as it is because it is missing a lot of stuff from it. For example it doesn’t first check if the player doesn’t have any saved data.