Introduction
Hey! This is my first community tutorial so point out anything that is wrong.
Anyways, today I wanted to explain how one would go about creating a global leaderboard in a GUI. Now, there are tons and tons of tutorials on how to make global leaderboards with SurfaceGuis, but global leaderboards with ScreenGuis are a bit more tricky.
Things i suggest before completing this tutorial
DISCLAIMER: There are most likely other ways to do this, I’m going to be showing the way that worked best for me
Lets Get Started
Let’s first set up our global leaderboard system
Lets create a folder, a empty script, and a ScreenGui for now!
Also feel free to name your scripts and gui’s different than mine just know that our code will look a bit different!
In our LeaderboardHandler
script in ServerScriptService
let’s right a few lines of code.
--// SERVICES //--
local Replicated = game:GetService("ReplicatedStorage")
local DataStoreService = game:GetService('DataStoreService')
local Players = game:GetService('Players')
--// DATASTORE //--
local DataStore = DataStoreService:GetOrderedDataStore('Test')
--// FOLDER //--
local Folder = Replicated:WaitForChild('Leaderboard') -- YOUR FOLDER IN REPLICATED STORAGE TO KEEP ENTRIES
--// SETTINGS //--
local EntriesPerPage = 50
local EntriesPerPage = 5
local RefreshTime = 60 -- In Seconds
-- We'll add more here soon!
Lets also create our ScreenGui and a few scripts!
Here is a quick GUI I made, yours can look completely different!
Next, let’s create a template for entries for the Global Leaderboard!
Here is what the inside of your ScreenGui should look like with the addition of a new Local Script
!
Make sure that the scrolling frame canvas size is set to {0,0},{0,0}
and AutomaticCanvasSize
is se to Y
looking like this:
The Main System
First, let’s figure out what we need to do for this global leaderboard system to actually work!
In the server, we are going to have a function
that loops every x seconds or the refresh time. This function will sort through the sorted datastore and grab every entry and either:
- Create a new Value Instance at the entry rank.
// or // - Update a value instance at the entry rank that already exists
In our LocalScript, we will have an event that detects whenever a new Value Instance is created. Once it is created we will attach a function that detects if the value updates. Once either of these events fire we can update our ScreenGui
!
Visual I made (don’t judge the quality)
Let’s Start Coding!
In our LeaderboardHandler script in ServerScriptService
let’s start to begin with a function that loops!
--// SERVICES //--
local Replicated = game:GetService("ReplicatedStorage")
local DataStoreService = game:GetService('DataStoreService')
local Players = game:GetService('Players')
--// DATASTORE //--
local DataStore = DataStoreService:GetOrderedDataStore('Test')
--// FOLDER //--
local Folder = Replicated:WaitForChild('Leaderboard') -- YOUR FOLDER IN REPLICATED STORAGE TO KEEP ENTRIES
--// SETTINGS //--
local EntriesPerPage = 50
local EntriesPerPage = 5
local RefreshTime = 60 -- In Seconds
-- // FUNCTIONS //--
local function Main()
-- Going to add stuff here in a second!
end
-- // LOOP // --
while true do
Main()
task.wait(RefreshTime)
end
In our Main
function let’s start to go through the entries in our datastore!
local function Main()
local success, pages = pcall(function()
return DataStore:GetSortedAsync(false, EntriesPerPage)
end)
if success then
for i=0,TotalEntires,EntriesPerPage do
local entries = pages:GetCurrentPage()
for rank, entry in pairs(entries) do
updateValue(rank, entry.key, entry.value)
end
if pages.IsFinished then
break
else
pages:AdvanceToNextPageAsync()
end
end
end
end
Let’s create a new function that creates or updates an Instance, which shouldn’t be hard at all!
local function updateValue(rank, key, value)
if Folder:FindFirstChild(rank) then
local found = Folder:FindFirstChild(rank)
if found.Key.Value ~= key then
found.Key.Value = key
found.Value.Value = value
end
else
local new = Instance.new('StringValue', Folder)
new.Name = rank
local newKey = Instance.new('StringValue',new)
local newValue = Instance.new('StringValue',new)
newKey.Name = 'Key'
newValue.Name = 'Value'
newKey.Value = key
newValue.Value = value
end
end
Now, let’s move onto our LocalScript
!
Let’s get the basics out of the way.
--// SERVICES //--
local Replicated = game:GetService('ReplicatedStorage')
--// FOLDER //--
local Folder = Replicated:WaitForChild("Leaderboard")
--// TEMPLATE //--
local Template = script:WaitForChild("Template")
--// FUNCTIONS // --
local function UpdateEntry(instance)
end
local function Set()
end
--// EVENTS // --
Folder.ChildAdded:Connect(UpdateEntry)
Let’s now work on our UpdateEntry
function!
This function fires whenever a new instance or child is added to the folder.
local function UpdateEntry(instance : Instance)
if instance:IsA("StringValue") then
local Rank = instance.Name
local Key = instance:FindFirstChild('Key')
local Value = instance:FindFirstChild('Value')
local Values = {Key; Value;}
if ScrollingFrame:FindFirstChild(Rank) then
local found = ScrollingFrame:FindFirstChild(Rank)
found:FindFirstChild('Name').Text = tostring(Key.Value)
found:FindFirstChild('Rank').Text = tostring(Rank)
found:FindFirstChild('Value').Text = tostring(Value.Value)
else
local new = Template:Clone()
new.Parent = ScrollingFrame
new.LayoutOrder = Rank
new:FindFirstChild('Name').Text = tostring(Key.Value)
new:FindFirstChild('Rank').Text = tostring(Rank)
new:FindFirstChild('Value').Text = tostring(Value.Value)
end
for _, v in pairs(Values) do
v.Changed:Connect(function()
UpdateEntry(instance)
end)
end
end
end
This UpdateEntry function handles all of the scrolling frame sorting and template creating!
Finally, let’s work on the set function.
This set function will fire once a player joins getting all of the entries already in ReplicatedStorage
local function Set()
for _, item in pairs(Folder:GetChildren()) do
UpdateEntry(item)
end
end
Set()
Once all of these elements are put together it should work!
Conclusion
Full Scripts
Server (LeaderboardHandler):
--// SERVICES //--
local Replicated = game:GetService("ReplicatedStorage")
local DataStoreService = game:GetService('DataStoreService')
local Players = game:GetService('Players')
--// DATASTORE //--
local DataStore = DataStoreService:GetOrderedDataStore('Test')
--// FOLDER //--
local Folder = Replicated:WaitForChild('Leaderboard') -- YOUR FOLDER IN REPLICATED STORAGE TO KEEP ENTRIES
--// SETTINGS //--
local TotalEntires = 50
local EntriesPerPage = 5
local RefreshTime = 15 -- In Seconds
-- // FUNCTIONS //--
local function updateValue(rank, key, value)
if Folder:FindFirstChild(rank) then
local found = Folder:FindFirstChild(rank)
if found.Key.Value ~= key then
found.Key.Value = key
found.Value.Value = value
end
else
local new = Instance.new('StringValue', Folder)
new.Name = rank
local newKey = Instance.new('StringValue',new)
local newValue = Instance.new('StringValue',new)
newKey.Name = 'Key'
newValue.Name = 'Value'
newKey.Value = key
newValue.Value = value
end
end
local function Main()
local success, pages = pcall(function()
return DataStore:GetSortedAsync(false, EntriesPerPage)
end)
if success then
for i=0,TotalEntires,EntriesPerPage do
local entries = pages:GetCurrentPage()
for rank, entry in pairs(entries) do
updateValue(rank, entry.key, entry.value)
end
if pages.IsFinished then
break
else
pages:AdvanceToNextPageAsync()
end
end
end
end
-- // LOOP // --
while true do
print('Refreshing')
Main()
task.wait(RefreshTime)
end
Client (ClientHandler):
--// SERVICES //--
local Replicated = game:GetService('ReplicatedStorage')
--// FOLDER //--
local Folder = Replicated:WaitForChild("Leaderboard")
--// TEMPLATE //--
local Template = script:WaitForChild("Template")
--// UI //--
local ui = script.Parent
local Main = ui.Main
local ScrollingFrame = Main.ScrollingFrame
--// FUNCTIONS // --
local function UpdateEntry(instance : Instance)
if instance:IsA("StringValue") then
local Rank = instance.Name
local Key = instance:FindFirstChild('Key')
local Value = instance:FindFirstChild('Value')
local Values = {Key; Value;}
if ScrollingFrame:FindFirstChild(Rank) then
local found = ScrollingFrame:FindFirstChild(Rank)
found:FindFirstChild('Name').Text = tostring(Key.Value)
found:FindFirstChild('Rank').Text = tostring(Rank)
found:FindFirstChild('Value').Text = tostring(Value.Value)
else
local new = Template:Clone()
new.Parent = ScrollingFrame
new.LayoutOrder = Rank
new:FindFirstChild('Name').Text = tostring(Key.Value)
new:FindFirstChild('Rank').Text = tostring(Rank)
new:FindFirstChild('Value').Text = tostring(Value.Value)
end
for _, v in pairs(Values) do
v.Changed:Connect(function()
UpdateEntry(instance)
end)
end
end
end
local function Set()
for _, item in pairs(Folder:GetChildren()) do
UpdateEntry(item)
end
end
Set()
--// EVENTS // --
Folder.ChildAdded:Connect(UpdateEntry)
Open Source Baseplate:
Tutorial.rbxl (46.2 KB)
If you need to reach out to me here our my socials:
Discord: Towphy#6174
Twitter: https://twitter.com/towphyReal
Please ask any sort of questions or suggestions you have!
This is my first tutorial!
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
0 voters