Roblox GUI Maker
← 全部教程

数据

如何制作 Roblox 全局排行榜 GUI

全局排行榜按某个统计(比如总金币)给每个玩家排名,而且排名跨服保留。难的不是 GUI —— 而是用 OrderedDataStore 存储可排序数据并把前列玩家读回来。本指南覆盖完整闭环:保存分数、取前 10 名、把它们渲染成行。从排行榜模板开始可以得到行布局。

打开排行榜 模板 →

1. 用 OrderedDataStore 存储可排名数据

OrderedDataStore 保持值可排序。用玩家的 UserId 当键、分数当值,这样每个玩家只出现一次。

local DataStoreService = game:GetService("DataStoreService")
local scores = DataStoreService:GetOrderedDataStore("CoinsLeaderboard")

local function saveScore(player, coins)
	scores:UpdateAsync(tostring(player.UserId), function(old)
		return math.max(old or 0, coins)
	end)
end

2. 读取前列玩家

GetSortedAsync 按顺序返回条目。传 false 表示降序(最高在前)和页大小。GetCurrentPage 给出排好序的 { key, value } 列表。

local function getTop(n)
	local page = scores:GetSortedAsync(false, n)
	local entries = {}
	for _, entry in ipairs(page:GetCurrentPage()) do
		local userId = tonumber(entry.key)
		local player = game:GetService("Players"):GetNameFromUserIdAsync(userId)
		table.insert(entries, { name = player, score = entry.value })
	end
	return entries
end
提示: GetNameFromUserIdAsync 是一次网络调用 —— 把名字缓存起来,免得每次刷新都重新拉同一个玩家。

3. 把列表发给客户端并生成行

用一个 RemoteEvent 把前列列表发出去;每个客户端按条目生成一行。因为面板有 UIListLayout,挂上每一行就自动堆叠。

-- Server
local remote = game.ReplicatedStorage:WaitForChild("LeaderboardUpdate")
task.spawn(function()
	while true do
		remote:FireAllClients(getTop(10))
		task.wait(60) -- refresh once a minute
	end
end)

-- Client: make one row per entry, parented to the panel
local function makeRow(rank, name, score)
	local row = Instance.new("Frame")
	row.Size = UDim2.fromScale(1, 0.14)
	row.Parent = panel
	-- ...rank label, name label, score label...
	return row
end

常见问题

全局排行榜多久刷新一次?

OrderedDataStore 有严格的速率限制。缓存前列列表,用服务端循环每 30–60 秒刷新一次,绝不要在每次分数变化时刷新。

为什么一个玩家出现了两次?

你用了 UserId 以外的东西当键。永远用 tostring(player.UserId) 当键,这样每个玩家正好对应一条记录。