roblox-game-systems

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Game systems recipes

游戏系统实践方案

Every recipe follows the same contract:
  1. State lives on the server in a service module; persistent parts go through the data layer (
    roblox-data-stores
    ).
  2. Clients send intents through validated, rate-limited remotes (
    roblox-security
    ,
    roblox-networking
    ) and render state they receive (attributes, snapshots/deltas).
  3. Config is data: tunables in a shared/server config module (or live
    ConfigService
    configs).
  4. Lifecycle-safe: handles late joiners, respawns, leaving mid-action, and server shutdown.
SystemReference
Leaderstats, currency service, XP/levels, daily rewards, obby checkpointsreferences/progression.md
Round loop (intermission → match → results), teams, spawningreferences/round-system.md
Melee and ranged combat with server validation, cooldowns, damage attributionreferences/combat.md
Inventory, equipping tools, shop purchases (soft currency), pets that followreferences/inventory-shop.md
每个实践方案都遵循相同的契约:
  1. 状态保存在服务端的 service module 中;需要持久化的部分通过 data layer (
    roblox-data-stores
    )处理。
  2. 客户端通过经过校验和限流的 remotes(
    roblox-security
    、
    roblox-networking
    )发送意图,并渲染其收到的状态(attributes、snapshots/deltas)。
  3. 配置即数据:可调参数放在 shared/server config module 中(或使用实时
    ConfigService
    配置)。
  4. 生命周期安全:处理中途加入的玩家、重生、行动中途离开以及服务端关闭等场景。
系统参考资料
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
    profile.Data.coins
    ) — or make the profile table the balance store directly.
  • For display, clients read
    player:GetAttribute("Coins")
    and
    GetAttributeChangedSignal("Coins")
    .
    leaderstats
    (a Folder with
    IntValue
    s under the player) shows values in the player list.
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.Data.coins
    )——也可以直接让 profile table 充当余额存储。
  • 显示数据时,客户端读取
    player:GetAttribute("Coins")
    和
    GetAttributeChangedSignal("Coins")
    。
    leaderstats
    (玩家列表下包含
    IntValue
    的 Folder)会在玩家列表中显示数值。

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-architecture
,
roblox-security
,
roblox-data-stores
,
roblox-networking
,
roblox-characters-animation
,
roblox-monetization
,
roblox-ui
.
roblox-architecture
、
roblox-security
、
roblox-data-stores
、
roblox-networking
、
roblox-characters-animation
、
roblox-monetization
、
roblox-ui
。