Bây giờ bạn có thể phát hiện khi một người chơi đã thu thập một đồng xu, bạn cần đếm xem có bao nhiêu đồng xu mà người chơi đã thu thập và làm cho số lượng đó hiển thị trên bảng xếp hạng.
Tạo một mô-đun kịch bản để ghi lại việc thu thập đồng xu
Để xử lý việc lưu trữ và quản lý dữ liệu thu thập đồng xu của từng người chơi, bạn cần tạo một đối tượng ModuleScript để chứa một cấu trúc dữ liệu và các hàm truy cập dữ liệu thu thập đồng xu cho mọi người chơi. Các mô-đun kịch bản là mã có thể tái sử dụng mà các kịch bản khác có thể yêu cầu. Trong trường hợp này, CoinService yêu cầu mô-đun kịch bản này để có thể cập nhật dữ liệu thu thập đồng xu khi người chơi chạm vào đồng xu.
Trong ServerStorage, tạo một ModuleScript có tên PlayerData với mã sau:
```lua
local PlayerData = {}
PlayerData.COIN_KEY_NAME = "Coins"
local playerData = {
--[[
[userId: string] = {
["Coins"] = coinAmount: number
}
]]
}
local function defaultPlayerData()
return {
[PlayerData.COIN_KEY_NAME] = 0
}
end
local function getData(player)
local data = playerData[tostring(player.UserId)] or defaultPlayerData()
playerData[tostring(player.UserId)] = data
return data
end
function PlayerData.getValue(player, key)
return getData(player)[key]
end
function PlayerData.updateValue(player, key, updateFunction)
local data = getData(player)
local oldValue = data[key]
local newValue = updateFunction(oldValue)
data[key] = newValue
return newValue
end
return PlayerData
```Mô-đun kịch bản định nghĩa một bảng PlayerData chứa không hoặc nhiều bảng playerData, đại diện cho dữ liệu thu thập đồng xu cho một người chơi. Mọi kịch bản yêu cầu mô-đun kịch bản này sẽ nhận được cùng một bản sao của bảng PlayerData, cho phép nhiều kịch bản sửa đổi và chia sẻ dữ liệu thu thập đồng xu.
Khai báo các cấu trúc dữ liệu
Mô-đun kịch bản bắt đầu với một khai báo của một bảng rỗng, PlayerData, được trả về ở cuối kịch bản. Nó cũng chứa các phương thức truy cập để lấy và thiết lập giá trị trong bảng.
Bảng playerData chứa các chú thích mô tả cấu trúc của bảng, giúp mã dễ hiểu hơn. Trong trường hợp này, một bảng playerData chứa một userId và một trường tương ứng có tên là Coins đại diện cho số lượng đồng xu đã thu thập cho người chơi đó.
local PlayerData = {}
PlayerData.COIN_KEY_NAME = "Coins"
local playerData = {
--[[
[userId: string] = {
["Coins"] = coinAmount: number
}
]]
}
...
return PlayerDataĐịnh nghĩa một trình truy cập dữ liệu cục bộ
getData() là một hàm cục bộ lấy dữ liệu cho một bảng playerData cụ thể. Nếu một người chơi chưa thu thập đồng xu, nó sẽ trả về một bảng từ hàm defaultPlayerData() để đảm bảo mỗi người chơi có một số dữ liệu liên quan đến họ. Một quy ước phổ biến là tạo các hàm đơn giản, công khai để chuyển giao logic cho các hàm có phạm vi cục bộ thực hiện công việc nặng nhọc.
local function defaultPlayerData()
return {
[PlayerData.COIN_KEY_NAME] = 0
}
end
local function getData(player)
local data = playerData[tostring(player.UserId)] or defaultPlayerData()
playerData[tostring(player.UserId)] = data
return data
endĐịnh nghĩa các trình truy cập dữ liệu công khai
getValue() và updateValue() là các hàm công khai mà các kịch bản khác yêu cầu mô-đun kịch bản này có thể gọi. Trong trường hợp của chúng ta, CoinService sử dụng các hàm này để cập nhật dữ liệu thu thập đồng xu của một người chơi bất cứ khi nào người chơi đó chạm vào một đồng xu.
function PlayerData.getValue(player, key)
return getData(player)[key]
end
function PlayerData.updateValue(player, key, updateFunction)
local data = getData(player)
local oldValue = data[key]
local newValue = updateFunction(oldValue)
data[key] = newValue
return newValue
endTriển khai một bảng xếp hạng
Bạn có thể đại diện cho dữ liệu thu thập đồng xu một cách trực quan với một bảng xếp hạng trên màn hình. Roblox bao gồm một hệ thống tích hợp sẵn tự động tạo bảng xếp hạng bằng cách sử dụng giao diện người dùng mặc định.
Trong ServerStorage, tạo một ModuleScript có tên Leaderboard với mã sau:
```lua
local Leaderboard = {}
-- Tạo một bảng xếp hạng mới
local function setupLeaderboard(player)
local leaderstats = Instance.new("Folder")
-- 'leaderstats' là một tên được dự trữ mà Roblox nhận diện để tạo bảng xếp hạng
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
return leaderstats
end
-- Tạo một giá trị thống kê bảng xếp hạng mới
local function setupStat(leaderstats, statName)
local stat = Instance.new("IntValue")
stat.Name = statName
stat.Value = 0
stat.Parent = leaderstats
return stat
end
-- Cập nhật giá trị thống kê của một người chơi
function Leaderboard.setStat(player, statName, value)
local leaderstats = player:FindFirstChild("leaderstats")
if not leaderstats then
leaderstats = setupLeaderboard(player)
end
local stat = leaderstats:FindFirstChild(statName)
if not stat then
stat = setupStat(leaderstats, statName)
end
stat.Value = value
end
return Leaderboard
```Các phần sau đây mô tả cách bảng xếp hạng hoạt động chi tiết hơn.
Tạo một bảng xếp hạng
Hàm setupLeaderboard() tạo một thể hiện thư mục mới có tên là leaderstats và đặt nó làm con của người chơi được chỉ định. Roblox tự động nhận diện một thư mục có tên là leaderstats như một bộ chứa các thống kê và tạo một phần tử giao diện người dùng để hiển thị các thống kê. Nó yêu cầu các giá trị trong leaderstats được lưu trữ dưới dạng các đối tượng "giá trị" (chẳng hạn như StringValue, IntValue hoặc NumberValue).
-- Tạo một bảng xếp hạng mới
local function setupLeaderboard(player)
local leaderstats = Instance.new("Folder")
-- 'leaderstats' là một tên được dự trữ mà Roblox nhận diện để tạo bảng xếp hạng
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
return leaderstats
end
-- Tạo một giá trị thống kê bảng xếp hạng mới
local function setupStat(leaderstats, statName)
local stat = Instance.new("IntValue")
stat.Name = statName
stat.Value = 0
stat.Parent = leaderstats
return stat
endCập nhật thống kê của người chơi
setStat() là hàm công khai duy nhất trong mô-đun Leaderboard. Nó tạo các giá trị thống kê cho một người chơi được chỉ định hoặc cho bảng xếp hạng nếu nó chưa tồn tại.
FindFirstChild() nhận tên của một đối tượng và trả về đối tượng nếu nó tồn tại, hoặc nil nếu không. Đây là một phương pháp phổ biến và an toàn để tìm hiểu xem một đối tượng có tồn tại trước khi bạn sử dụng nó.
-- Cập nhật giá trị thống kê của một người chơi
function Leaderboard.setStat(player, statName, value)
local leaderstats = player:FindFirstChild("leaderstats")
if not leaderstats then
leaderstats = setupLeaderboard(player)
end
local stat = leaderstats:FindFirstChild(statName)
if not stat then
stat = setupStat(leaderstats, statName)
end
stat.Value = value
endTích hợp các mô-đun kịch bản
Với cả hai mô-đun đã được thiết lập, yêu cầu chúng trong kịch bản CoinService để quản lý và hiển thị dữ liệu đồng xu của người chơi.
Trong ServerScriptService, thay thế mã của kịch bản CoinService hiện có bằng mã sau:
```lua
-- Khởi tạo các dịch vụ và biến
local Workspace = game:GetService("Workspace")
local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
-- Các mô-đun
local Leaderboard = require(ServerStorage.Leaderboard)
local PlayerData = require(ServerStorage.PlayerData)
local coinsFolder = Workspace.World.Coins
local coins = coinsFolder:GetChildren()
local COIN_KEY_NAME = PlayerData.COIN_KEY_NAME
local COOLDOWN = 10
local COIN_AMOUNT_TO_ADD = 1
local function updatePlayerCoins(player, updateFunction)
-- Cập nhật bảng đồng xu
local newCoinAmount = PlayerData.updateValue(player, COIN_KEY_NAME, updateFunction)
-- Cập nhật bảng xếp hạng đồng xu
Leaderboard.setStat(player, COIN_KEY_NAME, newCoinAmount)
end
-- Định nghĩa trình xử lý sự kiện
local function onCoinTouched(otherPart, coin)
if coin:GetAttribute("Enabled") then
local character = otherPart.Parent
local player = Players:GetPlayerFromCharacter(character)
if player then
-- Người chơi chạm vào một đồng xu
coin.Transparency = 1
coin:SetAttribute("Enabled", false)
updatePlayerCoins(player, function(oldCoinAmount)
oldCoinAmount = oldCoinAmount or 0
return oldCoinAmount + COIN_AMOUNT_TO_ADD
end)
task.wait(COOLDOWN)
coin.Transparency = 0
coin:SetAttribute("Enabled", true)
end
end
end
-- Thiết lập các trình lắng nghe sự kiện
for _, coin in coins do
coin:SetAttribute("Enabled", true)
coin.Touched:Connect(function(otherPart)
onCoinTouched(otherPart, coin)
end)
end
```Các thay đổi đối với kịch bản CoinService gốc bao gồm:
- Khai báo COIN_AMOUNT_TO_ADD là số lượng đồng xu sẽ thêm vào khi một người chơi thu thập một đồng xu, và COIN_KEY_NAME là tên khóa được định nghĩa trong PlayerData.
- Tạo hàm trợ giúp updatePlayerCoins() để cập nhật số lượng đồng xu của người chơi và thống kê bảng xếp hạng liên quan.
- Thay thế câu lệnh print() tạm thời trong onCoinTouched() bằng một cuộc gọi đến updatePlayerCoins().
Chơi thử
Chọn Test từ menu thả xuống và nhấp vào Play. Đi vào một đồng xu và xác nhận rằng bảng xếp hạng xuất hiện ở góc và số lượng đồng xu của bạn tăng lên khi bạn thu thập thêm đồng xu.