Kho dữ liệu là một dịch vụ mà bạn có thể sử dụng để lưu và tải dữ liệu người chơi bền vững qua các phiên người chơi khác nhau. Chúng lưu trữ thông tin quan trọng, như tiến trình hoặc kho đồ của người chơi, và cho phép bạn truy xuất nó cho người chơi lần sau khi họ tham gia trò chơi của bạn. Nếu không có kho dữ liệu, người chơi sẽ mất toàn bộ tiến trình mỗi khi họ rời khỏi trò chơi.
Có hai loại kho dữ liệu: tiêu chuẩn và đã sắp xếp. Hướng dẫn này sử dụng kho dữ liệu đã sắp xếp, lưu trữ dữ liệu mà bạn có thể xếp hạng và sắp xếp theo số, và truy xuất theo thứ tự tăng dần hoặc giảm dần dựa trên giá trị số đã lưu.
Sử dụng tệp Hướng dẫn tạo bảng xếp hạng Gold Rush - Bắt đầu .rbxl làm điểm khởi đầu và tệp Hướng dẫn tạo bảng xếp hạng Gold Rush - Hoàn thành .rbxl làm tham chiếu, hướng dẫn này cung cấp cho bạn nền tảng cần thiết để tạo bảng xếp hạng người chơi tùy chỉnh, bao gồm hướng dẫn về:
- Lưu trữ điểm vàng trong kho dữ liệu đã sắp xếp.
- Lấy và sắp xếp các điểm số hàng đầu toàn cầu trên tất cả các máy chủ.
- Hiển thị các điểm số hàng đầu trong bảng xếp hạng tùy chỉnh trong giao diện người dùng.
- Tự động làm mới bảng xếp hạng tùy chỉnh sau vài giây.
Cuối hướng dẫn này, bạn nên có các thành phần sau:
- Trong ServerScriptService:
- Một script GoldManager đã được cập nhật để lưu điểm số của người chơi vào kho dữ liệu đã sắp xếp cho bảng xếp hạng.
- Một module script LeaderboardRemoteHandler mới để lấy và trả về danh sách đã sắp xếp của các điểm số hàng đầu từ bảng xếp hạng.
- Một script LeaderboardManager mới để phản hồi các yêu cầu dữ liệu bảng xếp hạng từ client, hoạt động như một cầu nối giữa client trong LeaderboardGuiScript và server trong LeaderboardManager.
- Trong StarterGui, một script local mới LeaderboardGuiScript để hiển thị giao diện bảng xếp hạng người chơi.

Bật quyền truy cập Studio vào các dịch vụ API
Kho dữ liệu không được lưu trữ cục bộ trên thiết bị của bạn, vì vậy trò chơi của bạn phụ thuộc vào giao tiếp giữa các máy chủ với backend của Roblox để sử dụng chúng. Theo mặc định, Studio hạn chế giao tiếp này để ngăn chặn lạm dụng hoặc sử dụng sai. Quyền truy cập vào các dịch vụ API trong Studio bị vô hiệu hóa cho đến khi bạn bật nó để đảm bảo rằng chỉ các trò chơi đáng tin cậy mới có thể đọc và ghi vào máy chủ backend của Roblox.
Để bật quyền truy cập Studio vào các dịch vụ API để bạn có thể sử dụng kho dữ liệu:
- Mở tệp Hướng dẫn tạo bảng xếp hạng Gold Rush - Bắt đầu trong Studio. Tệp điểm khởi đầu này đã bao gồm mã từ hướng dẫn Lưu dữ liệu người chơi và khung giao diện cho bảng xếp hạng người chơi.
- Trở lại Studio, đi tới Tệp ⟩ Cài đặt Trải nghiệm ⟩ Bảo mật.
- Bật Bật quyền truy cập Studio vào các dịch vụ API.
- Lưu thay đổi của bạn.
Tạo một kho dữ liệu đã sắp xếp
Khi tạo một kho dữ liệu, bạn nên luôn gọi DataStoreService từ một Script phía máy chủ. Điều này là quan trọng vì:
- Roblox chặn toàn bộ quyền truy cập kho dữ liệu từ client để chỉ server có quyền truy cập và chỉnh sửa dữ liệu người chơi bền vững.
- Các script phía máy chủ chạy trong một môi trường trung tâm, đảm bảo rằng dữ liệu được đọc và ghi vào kho dữ liệu của bạn là chính xác và hợp lệ.
- Vì các script phía client chạy trên thiết bị của người chơi, bất kỳ người chơi nào cũng có thể khai thác trò chơi và đánh cắp hoặc ghi đè dữ liệu của những người chơi khác nếu client có quyền truy cập vào các kho dữ liệu của bạn.
Bạn cũng nên đặt tên cho kho dữ liệu của bạn một cách độc nhất để giữ cho dữ liệu của bạn được tổ chức và ngăn chặn việc chồng chéo hoặc xung đột trong các kho dữ liệu khác nhau. Trong hướng dẫn này, kho dữ liệu cho bảng xếp hạng được gọi là GlobalLeaderboard.
Để tạo kho dữ liệu đã sắp xếp GlobalLeaderboard:
Mở script GoldManager hiện có dưới ServerScriptService.

Dưới kho dữ liệu PlayerGold hiện có, gọi GetOrderedDataStore với chuỗi "GlobalLeaderboard". Điều này tạo ra một kho dữ liệu đã sắp xếp để lưu điểm số của người chơi khi họ kiếm vàng.
local leaderboardStore = DataStoreService:GetOrderedDataStore("GlobalLeaderboard")
Sau khi tạo kho dữ liệu, bạn có thể tham chiếu kho dữ liệu này trong các script khác nhau. Ví dụ, bạn có thể gọi GetOrderedDataStore ở cả script GoldManager và module script LeaderboardManager mà bạn sẽ tạo sau trong hướng dẫn này. Việc tham chiếu cùng một kho dữ liệu ở hai vị trí không có nghĩa là bạn sao chép dữ liệu; điều đó chỉ có nghĩa là hai script đang truy cập vào cùng một nơi lưu trữ trung tâm, giống như hai đồng đội sử dụng một thư mục để chia sẻ thông tin.
Gửi dữ liệu người chơi đến bảng xếp hạng
Các kho dữ liệu được cấu thành từ các khóa, xác định dữ liệu, và các giá trị, lưu trữ dữ liệu. Không giống như các kho dữ liệu tiêu chuẩn, các kho dữ liệu đã sắp xếp cho phép bạn sắp xếp dữ liệu theo giá trị, điều này làm cho chúng lý tưởng để tạo ra các bảng xếp hạng.
Mỗi mục trong một kho dữ liệu đã sắp xếp được lưu trữ dưới một khóa độc nhất mà bạn có thể xếp hạng và sắp xếp theo số, và sau đó truy xuất theo thứ tự tăng dần hoặc giảm dần dựa trên các giá trị số đã lưu. Điều này có nghĩa là bạn có thể sử dụng các kho dữ liệu đã sắp xếp để, ví dụ, hiển thị một danh sách 3 người hàng đầu được cập nhật trong thời gian thực khi người chơi trong trò chơi của bạn thu thập nhiều vàng hơn.
| Khóa | Giá trị | |
|---|---|---|
| Mô tả | Một khóa là một định danh chuỗi độc nhất mà bạn có thể sử dụng để truy cập một phần dữ liệu cụ thể, như ID người dùng của người chơi. Các khóa cho phép bạn tổ chức dữ liệu của mình để bạn có thể dễ dàng quản lý và gỡ lỗi. | Một giá trị là dữ liệu số thực tế mà bạn muốn lưu hoặc tải, như điểm số của người chơi. Các giá trị cho phép bạn lưu trữ tiến trình giữa các phiên, cũng như truy xuất dữ liệu người chơi lần sau họ tham gia trò chơi của bạn. |
| Các định dạng được phép | Chỉ có thể là chuỗi. Nếu bạn đang sử dụng các số, như ID người dùng, hãy chuyển đổi chúng thành chuỗi bằng cách sử dụng tostring(). | Chỉ có thể là số. |
| Ví dụ | "Player_A", "TopScore", "123456" (ID người dùng dưới dạng chuỗi) | 100, 3.14, 0, -25 |
Bây giờ bạn đã tạo kho dữ liệu đã sắp xếp GlobalLeaderboard, hãy cập nhật chức năng saveGold hiện có trong script GoldManager để gửi điểm vàng của người chơi đến bảng xếp hạng tùy chỉnh của bạn với SetAsync:
local function saveGold(player, value)
local userId = player.UserId
local success, err = pcall(function()
goldStore:SetAsync(userId, value)
leaderboardStore:SetAsync(tostring(userId), value)
end)
if not success then
warn("Không thể lưu vàng cho", player.Name, ":", err)
end
end
Bạn có thể nghĩ về kho dữ liệu đã sắp xếp GlobalLeaderboard như một thư mục chia sẻ: SetAsync thêm nội dung vào thư mục, trong khi GetSortedAsync (mà bạn sẽ tạo sau trong module script LeaderboardManager) đọc nội dung của thư mục và sắp xếp nó theo điểm số.
Lấy các điểm số bảng xếp hạng
Để lấy các điểm số bảng xếp hạng, bạn nên sử dụng ModuleScript. Các module script cho phép bạn tổ chức và tái sử dụng mã của mình qua nhiều script khác nhau. Thay vì sao chép cùng một logic vào các nơi khác nhau, bạn có thể viết nó một lần trong một module script và gọi nó từ bất kỳ đâu cần thiết.
Khi bạn lưu trữ logic bảng xếp hạng của mình trong một module, cả trình xử lý giao diện người dùng và các script phía máy chủ đều có thể sử dụng cùng một hàm để lấy các điểm số hàng đầu của người chơi. Nếu bạn cần, ví dụ, cập nhật cách mà tên người dùng được lấy hay cách mà các điểm số được sắp xếp, bạn chỉ cần thay đổi mã ở một nơi. Sau khi bạn cập nhật module, tất cả các script sử dụng nó cũng sẽ tự động nhận được hành vi đã cập nhật.
Bảng xếp hạng tùy chỉnh của bạn sử dụng các phương thức kho dữ liệu đã sắp xếp sau đây để chia sẻ dữ liệu giữa các máy chủ khác nhau:
- SetAsync (từ script GoldManager) để gửi điểm số người chơi đến kho dữ liệu đã sắp xếp GlobalLeaderboard.
- GetSortedAsync (trong module script) để lấy các điểm số hàng đầu từ tất cả các máy chủ từ cùng một kho dữ liệu. Phương thức GetSortedAsync là đặc quyền của các kho dữ liệu đã sắp xếp và có thể truy xuất nhiều khóa đã sắp xếp dựa trên một thứ tự sắp xếp cụ thể, kích thước trang, và các giá trị tối thiểu và tối đa.
Để lấy các điểm số bảng xếp hạng:
Trong ServerScriptService, tạo một ModuleScript mới gọi là LeaderboardManager.
Ở đầu module script, gọi GetOrderedDataStore với chuỗi "GlobalLeaderboard". Việc tham chiếu cùng một kho dữ liệu đã sắp xếp mà bạn đã tạo trong script GoldManager sẽ cho phép giao diện người dùng của bảng xếp hạng lấy và sắp xếp các điểm số người chơi hàng đầu sau này.
local DataStoreService = game:GetService("DataStoreService")local Players = game:GetService("Players")local leaderboardStore = DataStoreService:GetOrderedDataStore("GlobalLeaderboard")Chuẩn bị một bảng module để chứa tất cả các hàm và dữ liệu mà bạn muốn cung cấp cho các script khác.
local leaderboardManager = {}Tạo một hàm gọi là GetTopScores để lấy các điểm số người chơi hàng đầu. Hàm này:
- Gọi GetSortedAsync để lấy số lượng điểm số hàng đầu trong thứ tự giảm dần. Nếu cuộc gọi thất bại, một danh sách trống sẽ được trả về để ngăn chặn phần còn lại của mã bạn bị sập.
- Lặp qua bảng xếp hạng để lấy một bảng các mục với GetCurrentPage và tên người dùng của người chơi với GetNameFromUserIdAsync.
- Thêm mỗi kết quả vào một danh sách cuối cùng và xây dựng một bảng xếp hạng với tên người dùng của người chơi và điểm số của họ.
- Trả về danh sách cuối cùng của các người chơi và gửi dữ liệu bảng xếp hạng trở lại bất kỳ script nào gọi hàm leaderboardManager.GetTopScores này.
function leaderboardManager.GetTopScores(limit)local success, pages = pcall(function()return leaderboardStore:GetSortedAsync(false, limit)end)if not success or not pages thenreturn {}endlocal results = {}for _, entry in ipairs(pages:GetCurrentPage()) dolocal userId = tonumber(entry.key)local score = entry.valuelocal username = "Không xác định"local ok, name = pcall(function()return Players:GetNameFromUserIdAsync(userId)end)if ok thenusername = nameendtable.insert(results, {Username = username,Score = score})endreturn resultsendLàm cho module có thể sử dụng bằng cách trả về bảng module mà bạn đã tạo trước đó. Mỗi khi bạn tạo một module script, bạn phải trả về bảng module để các script khác có thể truy cập nó và gọi các hàm bên trong nó.
return leaderboardManager
Yêu cầu dữ liệu bảng xếp hạng từ máy chủ
Để giao diện người dùng client hiển thị các điểm số bảng xếp hạng, máy chủ phải phản hồi khi client yêu cầu dữ liệu. Một RemoteFunction cho phép client yêu cầu thông tin từ máy chủ và chờ đợi phản hồi.
Để yêu cầu dữ liệu bảng xếp hạng từ máy chủ:
- Trong ReplicatedStorage, chèn một RemoteFunction gọi là LeaderboardRemote. Hàm remote này hoạt động như cầu nối giữa script giao diện người dùng trên client và logic bảng xếp hạng trên server.
- Trong ServerScriptService, tạo một script gọi là LeaderboardRemoteHandler. Trong script này:
Gọi ReplicatedStorage (không gian chia sẻ giữa client và server), ServerScriptService (nơi chứa module bảng xếp hạng), và leaderboardRemote (hàm remote mà client sẽ gọi để yêu cầu dữ liệu bảng xếp hạng).
local ReplicatedStorage = game:GetService("ReplicatedStorage")local ServerScriptService = game:GetService("ServerScriptService")local leaderboardRemote = ReplicatedStorage:WaitForChild("LeaderboardRemote")Tải module LeaderboardManager mà bạn đã tạo trước đó, bao gồm hàm lấy các điểm số hàng đầu từ kho dữ liệu đã sắp xếp.
local leaderboardManager = require(ServerScriptService:WaitForChild("LeaderboardManager"))Đặt hành vi cho khi client gọi InvokeServer. Máy chủ phản hồi bằng cách lấy ba điểm số hàng đầu và gửi kết quả trở lại client.
leaderboardRemote.OnServerInvoke = function(player)return leaderboardManager.GetTopScores(3)end
Hiển thị dữ liệu trong giao diện bảng xếp hạng tùy chỉnh
Sau khi thiết lập các script phía máy chủ, hãy tạo một script local để lấy ba người chơi hàng đầu mỗi 3 giây và hiển thị kết quả trong bảng xếp hạng UI toàn cầu trong trò chơi.
Để hiển thị dữ liệu trong bảng xếp hạng tùy chỉnh của bạn:
Trong StarterGui ⟩ LeaderboardGui, tạo một script local gọi là LeaderboardGuiScript.
Ở đầu script, kết nối đến hàm remote. Gọi ReplicatedStorage để có quyền truy cập vào các đối tượng chia sẻ giữa máy chủ và client, sau đó gọi leaderboardRemote để cho phép client yêu cầu dữ liệu bảng xếp hạng từ máy chủ.
local ReplicatedStorage = game:GetService("ReplicatedStorage")local leaderboardRemote = ReplicatedStorage:WaitForChild("LeaderboardRemote")Tham chiếu đến các phần tử giao diện người dùng bảng xếp hạng hiện có dưới LeaderboardGui.
local gui = script.Parentlocal leaderboardFrame = gui:WaitForChild("LeaderboardFrame")local entriesFrame = leaderboardFrame:WaitForChild("EntriesFrame")local template = entriesFrame:WaitForChild("LeaderboardEntry")Tạo một hàm gọi là clearEntries để xóa các mục bảng xếp hạng cũ. Hàm này lặp qua tất cả các con của entriesFrame, nơi chứa các hàng bảng xếp hạng, và đảm bảo rằng bảng xếp hạng được làm mới hoàn toàn trước khi hiển thị dữ liệu mới.
local function clearEntries()for _, child in ipairs(entriesFrame:GetChildren()) doif child:IsA("TextLabel") and child.Name:match("^Row%d+$") thenchild:Destroy()endendendTạo một hàm gọi là renderLeaderboard để chèn và hiển thị dữ liệu người chơi trong các hàng bảng xếp hạng. Đối tượng data là một bảng được trả về bởi máy chủ chứa các mục với tên người dùng của người chơi và điểm số.
local function renderLeaderboard(data)clearEntries()for i, entry in ipairs(data) dolocal row = template:Clone()row.Name = "Row" .. irow.Visible = truerow.LayoutOrder = irow.Text = string.format("%d%s vị trí: %s - %d",i, i == 1 and "st" or i == 2 and "nd" or i == 3 and "rd" or "th",entry.Username, entry.Score)row.Parent = entriesFrameendendTạo một vòng lặp để định kỳ lấy dữ liệu bảng xếp hạng. Mỗi 3 giây, vòng lặp sẽ chạy và gọi máy chủ bằng cách sử dụng hàm InvokeServer mà bạn đã tạo trước đó trong script LeaderboardRemoteHandler. Nếu cuộc gọi thành công, giao diện sẽ làm mới với các điểm số đã cập nhật.
while true dolocal success, data = pcall(function()return leaderboardRemote:InvokeServer()end)if success and data thenrenderLeaderboard(data)endtask.wait(3)end
Mã cuối cùng
Xem các đoạn mã sau đây cho các script GoldManager, LeaderboardManager, LeaderboardRemoteHandler, và LeaderboardGuiScript hoàn chỉnh. Bạn có thể dán và chạy chúng trực tiếp trong tệp Hướng dẫn tạo bảng xếp hạng Gold Rush - Bắt đầu .rbxl trong Studio.
GoldManager
Script GoldManager tạo một kho dữ liệu đã sắp xếp để quản lý các cập nhật bảng xếp hạng.
-- Nhận các dịch vụ
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local CollectionService = game:GetService("CollectionService")
local DataStoreService = game:GetService("DataStoreService")
-- Sự kiện remote để cập nhật UI
local uiEvent = ReplicatedStorage:WaitForChild("UIEvent")
-- Kho dữ liệu để lưu các mảnh vàng của người chơi
local goldStore = DataStoreService:GetDataStore("PlayerGold")
-- Kho dữ liệu đã sắp xếp để lưu vàng vào bảng xếp hạng
local leaderboardStore = DataStoreService:GetOrderedDataStore("GlobalLeaderboard")
-- Tạo một bộ sinh số ngẫu nhiên để định vị các mảnh vàng
local random = Random.new()
-- Bảng để lưu các mảnh vàng của người chơi cho một phiên duy nhất
local playerGold = {}
-- Hằng số
local GOLD_VALUE = 10 -- Giá trị của mỗi mảnh vàng
local GOLD_REGENERATION_BOUNDS = { -- Giới hạn khu vực dùng để định vị lại các mảnh vàng ngẫu nhiên
minX = -72,
maxX = 72,
minZ = -72,
maxZ = 72
}
local GOLD_REGEN_DELAY = 2 -- Thời gian trước khi một mảnh vàng tái sinh (tính bằng giây)
local AUTOSAVE_INTERVAL = 30 -- Tần suất lưu mảnh vàng của người chơi (tính bằng giây)
-- Hàm để xử lý việc người chơi thu thập một mảnh vàng
local function processGoldTouch(chunk, player)
-- Ẩn mảnh vàng khi người chơi thu thập nó
chunk.Parent = nil
-- Thêm mảnh vàng vào điểm số vàng của phiên hiện tại của người chơi
local userId = player.UserId
playerGold[userId] = (playerGold[userId] or 0) + GOLD_VALUE
print(player.Name, "hiện có", playerGold[userId], "vàng")
-- Cập nhật thanh điểm số UI để phản ánh điểm vàng mới cho phiên này
uiEvent:FireClient(player, {
gold = playerGold[userId],
doTween = true,
showAlert = false
})
-- Đợi một chút và sau đó tái sinh mảnh vàng vừa được thu thập ở một vị trí ngẫu nhiên
task.delay(GOLD_REGEN_DELAY, function()
-- Tái sinh mảnh vàng ở vị trí ngẫu nhiên mới
local nextPositionX = random:NextInteger(GOLD_REGENERATION_BOUNDS.minX, GOLD_REGENERATION_BOUNDS.maxX)
local nextPositionZ = random:NextInteger(GOLD_REGENERATION_BOUNDS.minZ, GOLD_REGENERATION_BOUNDS.maxZ)
chunk.CFrame = CFrame.new(nextPositionX, 50, nextPositionZ) -- Di chuyển mảnh vàng đến vị trí mới
chunk:SetAttribute("DropCollided", false) -- Đặt lại các cờ va chạm
chunk.Parent = workspace.GoldChunks
end)
end
-- Lặp qua tất cả các phần đã được gán nhãn bằng "Gold" và kết nối chúng với việc phát hiện va chạm
for _, chunk in ipairs(CollectionService:GetTagged("Gold")) do
chunk.Touched:Connect(function(otherPart)
local player = Players:GetPlayerFromCharacter(otherPart.Parent)
if player then
processGoldTouch(chunk, player)
end
end)
end
-- Hàm để lưu vàng của người chơi vào cả kho dữ liệu tiêu chuẩn và đã sắp xếp
local function saveGold(player, value)
local userId = player.UserId
local success, err = pcall(function()
goldStore:SetAsync(userId, value)
leaderboardStore:SetAsync(tostring(userId), value)
end)
if not success then
warn("Không thể lưu vàng cho", player.Name, ":", err)
end
end
-- Hàm để xử lý người chơi tham gia trò chơi
local function onPlayerAdded(player)
local userId = player.UserId
print(player.Name, "đã tham gia trò chơi")
-- Cố gắng tải vàng của người chơi từ kho dữ liệu
local success, storedGold = pcall(function()
return goldStore:GetAsync(userId)
end)
-- Thiết lập điểm số vàng phiên hiện tại bằng giá trị kho dữ liệu cho người chơi
local currentGold = if success and storedGold then storedGold else 0
playerGold[userId] = currentGold
-- Cập nhật giao diện với giá trị kho dữ liệu cho người chơi
uiEvent:FireClient(player, {
gold = currentGold,
doTween = false,
showAlert = not success
})
if success then
print("Đã tải", currentGold, "vàng cho", player.Name)
else
-- Thông báo người chơi rằng vàng của họ không thể được tải
uiEvent:FireClient(player, { showAlert = true })
warn("Không thể tải vàng cho", player.Name)
end
-- Bắt đầu coroutine tự động lưu để lưu vàng của người chơi mỗi 30 giây
coroutine.wrap(function()
while player.Parent do
task.wait(AUTOSAVE_INTERVAL)
if playerGold[userId] then
saveGold(player, playerGold[userId])
print("Tự động lưu", playerGold[userId], "vàng cho", player.Name)
end
end
end)()
end
-- Hàm để xử lý người chơi rời khỏi trò chơi
local function onPlayerRemoving(player)
local userId = player.UserId
print(player.Name, "đã rời khỏi trò chơi")
-- Kiểm tra xem vàng của người chơi đã được theo dõi chưa
if playerGold[userId] then
-- Lưu vàng của người chơi vào kho dữ liệu trước khi họ rời đi
saveGold(player, playerGold[userId])
end
end
-- Kết nối các sự kiện khi người chơi tham gia và rời khỏi
Players.PlayerAdded:Connect(onPlayerAdded)
Players.PlayerRemoving:Connect(onPlayerRemoving)
LeaderboardManager
Module script LeaderboardManager:
- Gọi GetSortedAsync() trên kho dữ liệu đã sắp xếp GlobalLeaderboard.
- Chuyển đổi các userId thành tên người dùng bằng cách sử dụng GetNameFromUserIdAsync.
- Trả về một danh sách các bảng { Username, Score } cho các người chơi có thứ hạng cao nhất.
- Được gọi bởi LeaderboardRemoteHandler bất cứ khi nào client yêu cầu dữ liệu bảng xếp hạng.
-- Nhận các dịch vụ
local Players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
-- Kho dữ liệu đã sắp xếp để lưu các điểm số bảng xếp hạng
local leaderboardStore = DataStoreService:GetOrderedDataStore("GlobalLeaderboard")
-- Bảng để lưu các điểm số bảng xếp hạng
local leaderboardManager = {}
-- Hàm để trả về các điểm số hàng đầu
function leaderboardManager.GetTopScores(limit)
-- Cố gắng truy xuất một trang đã sắp xếp của các mục bảng xếp hạng từ kho dữ liệu
local success, pages = pcall(function()
-- false = giảm dần (các điểm số cao nhất trước)
return leaderboardStore:GetSortedAsync(false, limit)
end)
-- Nếu cuộc gọi thất bại hoặc không trả về gì, ghi lại một cảnh báo và trả về bảng trống
if not success or not pages then
warn("Không thể lấy dữ liệu bảng xếp hạng")
return {}
end
-- Tạo một bảng để lưu dữ liệu người chơi hàng đầu
local topPlayers = {}
-- Lặp qua từng mục trên trang hiện tại của các kết quả bảng xếp hạng
for _, entry in ipairs(pages:GetCurrentPage()) do
local userId = tonumber(entry.key) -- Chuyển đổi khóa của mục thành số (userId đã được lưu dưới dạng chuỗi)
local score = entry.value -- Giá trị là điểm số của người chơi (số vàng)
local username = "Không xác định" -- Một tên mặc định trong trường hợp việc tìm kiếm thất bại
-- Cố gắng lấy tên người dùng của người chơi từ userId
local ok, name = pcall(function()
return Players:GetNameFromUserIdAsync(userId)
end)
-- Nếu việc tìm kiếm thành công, lưu tên người dùng thực
if ok then
username = name
end
-- Thêm người chơi này cùng điểm số của họ vào danh sách
table.insert(topPlayers, {
Username = username,
Score = score
})
end
-- Trả về danh sách đầy đủ của người chơi hàng đầu với tên người dùng và điểm số của họ
return topPlayers
end
-- Trả về module LeaderboardManager để các script khác có thể sử dụng
return leaderboardManager
LeaderboardRemoteHandler
Script LeaderboardRemoteHandler lấy và trả về ba điểm số hàng đầu cho client gọi.
-- Nhận các dịch vụ
local ServerScriptService = game:GetService("ServerScriptService") -- Truy cập các module phía máy chủ
local ReplicatedStorage = game:GetService("ReplicatedStorage") -- Các đối tượng giao tiếp chia sẻ giữa client và server
-- Chờ RemoteFunction mà client sử dụng để yêu cầu dữ liệu bảng xếp hạng
local leaderboardRemote = ReplicatedStorage:WaitForChild("LeaderboardRemote")
-- Tải module LeaderboardManager chứa hàm GetTopScores
local leaderboardManager = require(ServerScriptService:WaitForChild("LeaderboardManager"))
-- Thiết lập một trình xử lý cho khi client gọi chức năng RemoteFunction bảng xếp hạng
leaderboardRemote.OnServerInvoke = function(player)
-- Gọi module bảng xếp hạng để lấy ba điểm số hàng đầu và trả về chúng cho client
return leaderboardManager.GetTopScores(3)
end
LeaderboardGuiScript
Script local LeaderboardGuiScript:
- Yêu cầu dữ liệu bảng xếp hạng từ máy chủ mỗi 3 giây bằng cách sử dụng Class.RemoteHandler.InvokeServer|InvokeServer.
- Sử dụng một mẫu LeaderboardEntry ẩn để hiển thị mỗi hàng bảng xếp hạng.
- Định dạng mỗi hàng dưới dạng "1st place: Username - Score".
- Quản lý việc tạo, hiển thị và sắp xếp các hàng bảng xếp hạng bằng UIListLayout.
-- Nhận bộ nhớ chia sẻ để truy cập RemoteFunction
local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- Nhận RemoteFunction được sử dụng để yêu cầu dữ liệu bảng xếp hạng từ máy chủ
local leaderboardRemote = ReplicatedStorage:WaitForChild("LeaderboardRemote")
-- Tham chiếu giao diện người dùng
local gui = script.Parent -- LocalScript dưới ScreenGui
local leaderboardFrame = gui:WaitForChild("LeaderboardFrame") -- Thùng chính cho bảng xếp hạng
local entriesFrame = leaderboardFrame:WaitForChild("EntriesFrame") -- Khung mà các mục bảng xếp hạng sẽ xuất hiện
local template = entriesFrame:WaitForChild("LeaderboardEntry") -- Nhãn văn bản mẫu ẩn được sử dụng để tạo hàng
-- Hàm để xóa các hàng bảng xếp hạng cũ (nhưng không xóa mẫu)
local function clearEntries()
for _, child in ipairs(entriesFrame:GetChildren()) do
-- Chỉ xóa các nhãn có tên "Row1", "Row2", v.v. (để lại mẫu không chạm tới)
if child:IsA("TextLabel") and child.Name:match("^Row%d+$") then
child:Destroy()
end
end
end
-- Hàm để hiển thị dữ liệu bảng xếp hạng trên màn hình
local function renderLeaderboard(data)
-- Xóa các hàng cũ trước
clearEntries()
for i, entry in ipairs(data) do
local row = template:Clone() -- Nhân bản mẫu ẩn
row.Name = "Row" .. i -- Đặt cho nó một tên duy nhất
row.Visible = true -- Làm cho nó hiển thị
row.LayoutOrder = i -- Để UIListLayout sắp xếp đúng cách
-- Định dạng bảng xếp hạng: "1st vị trí: Tên người dùng - 123"
row.Text = string.format("%d%s vị trí: %s - %d",
i,
i == 1 and "st" or i == 2 and "nd" or i == 3 and "rd" or "th",
entry.Username,
entry.Score
)
-- Thêm dữ liệu vào giao diện
row.Parent = entriesFrame
end
end
-- Vòng lặp chính: cập nhật bảng xếp hạng mỗi 3 giây
while true do
-- Hỏi máy chủ về dữ liệu bảng xếp hạng
local success, data = pcall(function()
return leaderboardRemote:InvokeServer()
end)
if success and data then
-- Hiển thị kết quả trên bảng xếp hạng
renderLeaderboard(data)
else
warn("Không thể lấy dữ liệu bảng xếp hạng")
end
-- Chờ 3 giây trước khi cập nhật lại
task.wait(3)
end