roblox-game-systems
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseGame systems recipes
游戏系统实践方案
Every recipe follows the same contract:
- State lives on the server in a service module; persistent parts go through the data layer
().
roblox-data-stores - Clients send intents through validated, rate-limited remotes (,
roblox-security) and render state they receive (attributes, snapshots/deltas).roblox-networking - Config is data: tunables in a shared/server config module (or live configs).
ConfigService - Lifecycle-safe: handles late joiners, respawns, leaving mid-action, and server shutdown.
| System | Reference |
|---|---|
| Leaderstats, currency service, XP/levels, daily rewards, obby checkpoints | references/progression.md |
| Round loop (intermission → match → results), teams, spawning | references/round-system.md |
| Melee and ranged combat with server validation, cooldowns, damage attribution | references/combat.md |
| Inventory, equipping tools, shop purchases (soft currency), pets that follow | references/inventory-shop.md |
每个实践方案都遵循相同的契约:
- 状态保存在服务端的 service module 中;需要持久化的部分通过 data layer
()处理。
roblox-data-stores - 客户端通过经过校验和限流的 remotes(、
roblox-security)发送意图,并渲染其收到的状态(attributes、snapshots/deltas)。roblox-networking - 配置即数据:可调参数放在 shared/server config module 中(或使用实时 配置)。
ConfigService - 生命周期安全:处理中途加入的玩家、重生、行动中途离开以及服务端关闭等场景。
| 系统 | 参考资料 |
|---|---|
| leaderstats、货币服务、经验值/等级、每日奖励、obby 检查点 | references/progression.md |
| 回合循环(准备阶段 → 对局 → 结果)、队伍、角色生成 | references/round-system.md |
| 包含服务端校验、冷却和伤害归属的近战与远程战斗 | references/combat.md |
| 背包、装备工具、商店购买(软货币)、跟随玩家的宠物 | references/inventory-shop.md |
Currency service (the pattern every economy uses)
货币服务(所有经济系统采用的模式)
luau
--!strict
-- ServerScriptService/Server/Services/CurrencyService.luau
local Players = game:GetService("Players")
type Balances = { [Player]: number }
local MAX_BALANCE = 1e12
local CurrencyService = {}
local balances: Balances = {}
local function publish(player: Player)
player:SetAttribute("Coins", balances[player]) -- replicated to every client; UI listens
end
function CurrencyService.load(player: Player, saved: number?)
balances[player] = math.clamp(saved or 0, 0, MAX_BALANCE)
publish(player)
end
function CurrencyService.get(player: Player): number
return balances[player] or 0
end
-- Positive amount only; returns the new balance.
function CurrencyService.add(player: Player, amount: number, _source: string): number?
local balance = balances[player]
if balance == nil or not math.isfinite(amount) or amount <= 0 then
return nil
end
balances[player] = math.min(balance + math.floor(amount), MAX_BALANCE)
publish(player)
return balances[player]
end
-- Atomic check-and-spend; false if insufficient.
function CurrencyService.spend(player: Player, amount: number, _sink: string): boolean
local balance = balances[player]
if balance == nil or not math.isfinite(amount) or amount <= 0 or balance < amount then
return false
end
balances[player] = balance - math.floor(amount)
publish(player)
return true
end
Players.PlayerRemoving:Connect(function(player)
balances[player] = nil -- after the data layer has saved it
end)
return CurrencyService- One module owns each resource; nothing else writes it. Log sources/sinks to analytics
().
roblox-analytics-liveops - The in-memory balance is saved by the data layer (ProfileStore ) — or make the profile table the balance store directly.
profile.Data.coins - For display, clients read and
player:GetAttribute("Coins").GetAttributeChangedSignal("Coins")(a Folder withleaderstatss under the player) shows values in the player list.IntValue
luau
--!strict
-- ServerScriptService/Server/Services/CurrencyService.luau
local Players = game:GetService("Players")
type Balances = { [Player]: number }
local MAX_BALANCE = 1e12
local CurrencyService = {}
local balances: Balances = {}
local function publish(player: Player)
player:SetAttribute("Coins", balances[player]) -- replicated to every client; UI listens
end
function CurrencyService.load(player: Player, saved: number?)
balances[player] = math.clamp(saved or 0, 0, MAX_BALANCE)
publish(player)
end
function CurrencyService.get(player: Player): number
return balances[player] or 0
end
-- Positive amount only; returns the new balance.
function CurrencyService.add(player: Player, amount: number, _source: string): number?
local balance = balances[player]
if balance == nil or not math.isfinite(amount) or amount <= 0 then
return nil
end
balances[player] = math.min(balance + math.floor(amount), MAX_BALANCE)
publish(player)
return balances[player]
end
-- Atomic check-and-spend; false if insufficient.
function CurrencyService.spend(player: Player, amount: number, _sink: string): boolean
local balance = balances[player]
if balance == nil or not math.isfinite(amount) or amount <= 0 or balance < amount then
return false
end
balances[player] = balance - math.floor(amount)
publish(player)
return true
end
Players.PlayerRemoving:Connect(function(player)
balances[player] = nil -- after the data layer has saved it
end)
return CurrencyService- 每项资源由一个模块独占管理,其他任何模块都不得写入。将来源和消耗记录到 analytics()。
roblox-analytics-liveops - 内存中的余额由 data layer 保存(ProfileStore )——也可以直接让 profile table 充当余额存储。
profile.Data.coins - 显示数据时,客户端读取 和
player:GetAttribute("Coins")。GetAttributeChangedSignal("Coins")(玩家列表下包含leaderstats的 Folder)会在玩家列表中显示数值。IntValue
Design checklist for any new system
新系统的设计检查清单
- Where does authoritative state live, and how is it persisted?
- What can the client request, and how is each request validated and rate-limited?
- What happens on join mid-session, respawn, leave, teleport, and server shutdown?
- How is it tuned (config) and measured (analytics)?
- How does it behave with 1 player, full servers, and high latency?
- Is it streaming-safe on the client?
- 权威状态存放在哪里,如何持久化?
- 客户端可以请求什么,每个请求如何进行校验和限流?
- 对局中途加入、重生、离开、传送和服务端关闭时会发生什么?
- 如何调整配置(config)并衡量效果(analytics)?
- 只有 1 名玩家、服务器满员或网络延迟较高时,系统如何运行?
- 客户端上是否兼容 streaming?
Related skills
相关 Skills
roblox-architectureroblox-securityroblox-data-storesroblox-networkingroblox-characters-animationroblox-monetizationroblox-uiroblox-architectureroblox-securityroblox-data-storesroblox-networkingroblox-characters-animationroblox-monetizationroblox-ui