So i made a LeaderBoard for my Vibe game to let people see who is the best in my game but it doesn’t work.
This is my LeaderBoardHandler script what imports the ui but it doesn’t
local DataStoreService = game:GetService("DataStoreService")
local LevelLeaderBoard = DataStoreService:GetOrderedDataStore("DataStoreLevels")
local function Update ()
local Succes, ErrorMessage = pcall(function()
local Data = LevelLeaderBoard:GetSortedAsync(false, 5)
local LevelPage = Data:GetCurrentPage()
for rank, data in ipairs(LevelPage) do
local UserName = game.Players:GetNameFromUserIdAsync(tonumber(data.key))
local Name = UserName
local Level = data.Value
local isOnLeaderBoard = false
for i, v in pairs(game.Workspace["LeaderBoard - Levels"].Screen.SurfaceGui.MainFrame.Holder:GetChildren()) do
if v.Player.Text == Name then
isOnLeaderBoard = true
break
end
end
if Level and isOnLeaderBoard == false then
local NewLbFrame = game.ReplicatedStorage:WaitForChild("LevelLeaderBoard"):Clone()
NewLbFrame.Name.Text = Name
NewLbFrame.Level.Text = Level
NewLbFrame.Number.Text = rank.."."
NewLbFrame.Position = UDim2.new(0, 0, NewLbFrame.Position.Y.Offset + (30 * #game.Workspace["LeaderBoard - Levels"].Screen.SurfaceGui.MainFrame.Holder:GetChildren()), 0)
NewLbFrame.Parent = game.Workspace["LeaderBoard - Levels"].Screen.SurfaceGui.MainFrame.Holder
end
end
end)
if not Succes then
print(ErrorMessage)
end
end
while true do
for _, player in pairs(game.Players:GetPlayers()) do
LevelLeaderBoard:SetAsync(player.UserId, player.leaderstats.Level.Value)
end
for _, frame in pairs(game.Workspace["LeaderBoard - Levels"].Screen.SurfaceGui.MainFrame.Holder:GetChildren()) do
frame:Destroy()
end
Update()
print("Updated")
wait(60)
end
And this is my datastore where i save the levels
local currencyName = "Level"
local DataStore = game:GetService("DataStoreService"):GetDataStore("DataStoreLevels")
game.Players.PlayerAdded:Connect(function(player)
local folder = Instance.new("Folder")
folder.Name = "leaderstats"
folder.Parent = player
local currency = Instance.new("IntValue")
currency.Name = currencyName
currency.Parent = folder
local ID = currencyName.."-"..player.UserId
local savedData = nil
pcall(function()
savedData = DataStore:GetAsync(ID)
end)
if savedData ~= nil then
currency.Value = savedData
else
-- New player
currency.Value = 0
print("New player to the game")
end
while true do
wait(30)
currency.Value += 1
end
end)
game.Players.PlayerRemoving:Connect(function(player)
local ID = currencyName.."-"..player.UserId
DataStore:SetAsync(ID,player.leaderstats[currencyName].Value)
end)
game:BindToClose(function()
-- When game is ready to shutdown
for i, player in pairs(game.Players:GetPlayers()) do
if player then
player:Kick("This game is shutting down")
end
end
wait(5)
end)
So the levels are saving but it isn’t going onto the LeaderBoard.
One thing I am wondering about is why you’re kicking the players in your :BindToClose() function, instead of saving player data. This leads me to wonder if that’s preventing data from ever being written to the DataStore.
One other thing I’m noticing is it looks like you’re actually writing to 2 different keys (I assume you’re trying to set the player’s level data from both :SetAsync() calls?)
Do you mean like in both scripts cause one of the scripts is for just the player there levels it is the old script is whas made before and i didn’t change it.
So can you help me now with this cause i don’t understand why it doesn’t work cause like your saying things that are wrong but then you don’t help me your just saying what is wrong.
I think you don’t even understand how to do this cause i’m waiting for you and you don’t even look and now ty for not helping me and no-one will help me again and idk why no-one else is helping me.
You’re not handling pcall failures. pcall returns a status boolean. it’s false if the code in pcall errored. If that status boolean is false then pcall also returns the error message string.
local status, msg = pcall(function()
savedData = DataStore:GetAsync(ID)
end)
if not status then
warn(msg)
end
You should be pcalling the SetAsync too. Any roblox method that has the Async suffix needs a pcall.
Other than that the code looks fine; PlayerRemoving and BindToClose don’t execute fast enough in studio if you’ve been trying to test there. You need to go ingame to test those.
It is fine i used this script for now like more then 1 month and it works but the problem is in the other script cause that is making clones of a frame and the parent is becoming in the leaderboard but the problem is that this doesn’t work for some reason.
Didn’t notice your first codeblock. Did you add the pcall for the LevelLeaderBoard:SetAsync line?
Also for the GetSortedAsync load youd prefer to keep the protected code as small as possible and just filter out updating with that status boolean.
local Success, MsgOrLevelPage = pcall(function()
local Data = LevelLeaderBoard:GetSortedAsync(false, 5)
return Data:GetCurrentPage()
end
if not Success then
warn(MsgOrLevelPage)
else
for rank, data in ipairs(LevelPage) do
-- all that logic
end
end
if the load fails it just wont make the new leaderboard gui.
So i joined the game and i think the part where i have this:
if MsgOrLevelPage then
warn(MsgOrLevelPage)
else
It is warning in my game and it says this:
This is also the script right now what i changed cause you did say it to me to change it:
local DataStoreService = game:GetService("DataStoreService")
local LevelLeaderBoard = DataStoreService:GetOrderedDataStore("DataStoreLevels")
local function Update ()
local Success, MsgOrLevelPage = pcall(function()
local Data = LevelLeaderBoard:GetSortedAsync(false, 5)
return Data:GetCurrentPage()
end)
for rank, data in ipairs(MsgOrLevelPage) do
local UserName = game.Players:GetNameFromUserIdAsync(tonumber(data.key))
local Name = UserName
local Level = data.Value
local isOnLeaderBoard = false
if MsgOrLevelPage then
warn(MsgOrLevelPage)
else
for rank, data in ipairs(MsgOrLevelPage) do
for i, v in pairs(game.Workspace["LeaderBoard - Levels"].Screen.SurfaceGui.MainFrame.Holder:GetChildren()) do
if v.Player.Text == Name then
isOnLeaderBoard = true
break
end
end
if Level and isOnLeaderBoard == false then
local NewLbFrame = game.ReplicatedStorage:WaitForChild("LevelLeaderBoard"):Clone()
NewLbFrame.Name.Text = Name
NewLbFrame.Level.Text = Level
NewLbFrame.Number.Text = rank.."."
NewLbFrame.Position = UDim2.new(0, 0, NewLbFrame.Position.Y.Offset + (30 * #game.Workspace["LeaderBoard - Levels"].Screen.SurfaceGui.MainFrame.Holder:GetChildren()), 0)
NewLbFrame.Parent = game.Workspace["LeaderBoard - Levels"].Screen.SurfaceGui.MainFrame.Holder
end
end
end
end
end
Update()
while true do
for _, player in pairs(game.Players:GetPlayers()) do
LevelLeaderBoard:SetAsync(player.UserId, player.leaderstats.Level.Value)
end
for _, frame in pairs(game.Workspace["LeaderBoard - Levels"].Screen.SurfaceGui.MainFrame.Holder:GetChildren()) do
frame:Destroy()
end
Update()
print("Updated")
wait(60)
end