mcpField
R
roblox-simulator-economy

roblox-simulator-economy

github.com/gamedev-skills开发6.3k771 次安装4 天前更新
代码仓库

关于 roblox-simulator-economy

面向 Roblox 模拟器、放置类等游戏的 Luau 经济设计与实现技能,结合节奏计算、服务器控制的交易模式及可测试的数学模块。

主要功能

  1. 01计算升级与重生节奏
  2. 02实现服务器控制的购买
  3. 03处理离线收益与存档修复
  4. 04格式化大数并计算概率
  5. 05运行 Luau 经济数学测试

适用场景

  1. 01调整升级成本与重生时长
  2. 02实现批量购买和离线奖励
  3. 03防止客户端伪造货币购买
  4. 04显示大额余额与付费物品概率

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/gamedev-skills/awesome-gamedev-agent-skills --skill roblox-simulator-economy

安装后在 Claude Code 中输入/roblox-simulator-economy确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

agents/
openai.yaml
references/
formulas.md
server-patterns.md
scripts/
balance.luau
economy_math.luau
test_economy_math.luau

详细介绍

Roblox 模拟经营游戏经济系统

编写游戏玩法代码前,先用节奏表确定经济数值,然后再实现,确保所有数值都由服务器管理。代码面向 Roblox 滚动更新的平台 API,随附的脚本均为纯 Luau,并在 Studio 外使用 Lune 0.11.0 运行。

适用场景

  • 为模拟经营游戏、 tycoon、点击游戏或放置游戏选择或审查 baseCost、costGrowth、重生要求与倍率,或离线收益上限和效率。
  • 使用 Luau 编写升级、最大购买、货币、重生或离线收益代码。
  • 显示大数,或会损失精度的约 1e15 以上数值。
  • 添加使用 Robux 购买的蛋、箱子或转盘次数,或使用可通过 Robux 购买的货币购买的物品。

不适用场景: DataStore 读取、写入、会话锁定和重试 → roblox-datastores。深入设计远程协议和速率限制 → roblox-networking。商店和 HUD 布局 → roblox-ui + game-ui-ux。波次防御游戏的经济系统 → tower-defense。与引擎无关的存档格式问题 → save-systems。

工作流

  1. 检查。 找出当前存放货币、升级和重生数值的位置,以及会修改它们的脚本。列出所有涉及货币的 RemoteEvent 及其发送内容。
  2. 将数值写入一个配置表: 基础收入;每项升级的 baseCost、costGrowth、效果和 maxLevel;重生的 baseRequirement、requirementGrowth、multiplierPerRebirth;离线收益的 maxHours、efficiency。服务器和客户端都读取该配置表。
  3. 运行节奏计算器(路径相对于技能目录):lune run scripts/balance.luau --print-defaults > economy.json,编辑文件,然后运行 lune run scripts/balance.luau economy.json。查看 wait 和 vs prev 列,并调整数值,直到符合下方目标。--help 会列出所有字段及其允许范围;文件缺失、JSON 无效或字段超出范围时,会打印错误并以状态码 1 退出。
  4. 在服务器上实现下方的模式,并参考 references/server-patterns.md。将 scripts/economy_math.luau 原样复制到 ModuleScript,确保实际运行的数学逻辑与测试过的一致。
  5. 验证。 使用 lune run scripts/test_economy_math.luau(失败时以状态码 1 退出)验证数学逻辑;在 Studio 中使用 Server & Clients 进行游戏测试,检查购买、重生、退出和重新加入,以及无效远程参数。

公式

数量公式说明
下一级价格floor(baseCost * costGrowth ^ owned)对于会购买很多次的升级,取 1.07-1.15;对于稀有的大型升级,取 1.5-3
从等级 a 升到 b 的花费baseCost * g^a * (g^(b-a) - 1) / (g - 1)玩家实际支付的是各级价格向下取整后的总和,因此略低
最大购买按实际价格逐级计算,直到下一级价格超过余额或达到 maxLevel比使用对已向下取整价格不准确的对数公式更安全
重生要求 kbaseRequirement * requirementGrowth ^ k
重生倍率1 + k * multiplierPerRebirth加法增长缓慢;乘法增长(q ^ k)则呈指数增长
离线收入floor(min(away, maxHours * 3600) * rate * efficiency)离线时间为 0 或更少(时钟倒退)时,收益为 0

推导过程、重生等待时间比例公式及完整示例: references/formulas.md。

节奏目标(起点,而非规则)

  • 前期升级只需几秒。 在默认配置中,前 10 级每级需要 3–10 秒。
  • 每次重生所需时间只应比上次略长,例如 x1.2–x1.5。计算器的 vs prev 列显示这一比例。采用加法倍率时,该比例会随时间趋近于 requirementGrowth,因此 requirementGrowth = 3 时,比例会从 x2.0 增至 x2.7,按默认收入计算,第 8 次重生需要 137 天。requirementGrowth = 1.8 时,比例会从 x1.2 增至 x1.6。
  • 离线收益低于在线收益。 将效率设为 0.25–0.5,并将上限设为 8–12 小时,这样持续游玩仍比挂机更有价值,同时也不会让下线的玩家一无所获。

由服务端处理购买

RemoteEvent 只传递玩家想做什么(“购买升级 Income”),绝不传递数量或价格。服务端查询价格、检查余额、扣款并发放,期间不得让出执行权。

-- ServerScriptService/Economy.server.luau (excerpt; full version in references/server-patterns.md)
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local EconomyMath = require(ReplicatedStorage.Shared.EconomyMath)
local Config = require(ReplicatedStorage.Shared.EconomyConfig)

ReplicatedStorage.Remotes.BuyUpgrade.OnServerEvent:Connect(function(player: Player, upgradeId: unknown)
	local session = sessions[player]
	if not session or type(upgradeId) ~= "string" then return end
	local upgrade = Config.upgrades[upgradeId]
	if not upgrade then return end -- unknown id
	local owned = session.levels[upgradeId] or 0
	if owned >= upgrade.maxLevel then return end
	local price = EconomyMath.levelCost(upgrade.baseCost, upgrade.costGrowth, owned)
	if EconomyMath.trySpend(session.wallet, { [upgrade.currency] = price }) then
		session.levels[upgradeId] = owned + 1
	end
end)
  • trySpend 会在扣除任何货币前检查多货币费用中的每一种货币,并拒绝负数或非有限值费用。
  • 由服务端处理重生:将服务端余额与要求进行比较,然后重置钱包和等级并增加重生次数。绝不接受来自客户端的“我已重生”或余额。
  • 使用令牌桶为每位玩家的每个远程事件设置速率限制(roblox-networking)。

存档数据和离线时间

  • 加载时修复;绝不报错。 使用 sanitizeAmount(非数字、NaN、无穷大和负数均变为 0;小数向下取整)和 sanitizeLevel(还会限制到当前的 maxLevel)。丢弃未知升级 ID,并返回已修复内容的列表,以便旧版本和经过编辑的数据也能正常加载。
  • 绝不保存 NaN 或无穷大。 若除以零的结果进入钱包,应由同一套清理函数在保存前捕获。
  • 离线时间只能来自服务端时钟:玩家离开时由服务端保存 os.time();玩家加入时计算 away = os.time() - lastSeen。缺少 lastSeen 或其时间在未来时,均按当前时间处理,不发放收益。
  • 精度: Luau 数字是双精度数,可精确表示最大为 2^53(约 9e15)的整数。如果余额可能超过约 1e15,请改用尾数/指数对或以 10 为底的对数存储。

大数显示

EconomyMath.formatNumber(value, decimals?) 使用后缀 K、M、B、T、Qa、Qi、Sx、Sp、Oc、No、Dc、Ud、Dd、Td、Qad、Qid、Sxd、Spd、Ocd、Nod、Vg(1e63),之后使用科学计数法。

  • 进位错误: 999950 / 1000 = 999.95,四舍五入后会变成 "1000.0K"。先四舍五入;如果舍入后的值达到 1000,就切换到下一个后缀("1.0M")。测试覆盖了这种情况。
  • 仅在客户端格式化显示;绝不要将格式化后的字符串解析回数字。

付费随机物品(例如,蛋、箱子、抽奖)

当随机物品通过 Robux 直接购买,或通过用 Robux 购买的游戏内货币购买时,适用 Roblox 的付费随机物品指南。根据该页面:

  • 购买前展示所有可能的结果及其实际数值概率,以百分比表示,且总和恰好为 100%(较长的小数可以四舍五入,但需注明显示的总和可能不恰好为 100%)。
  • 概率修正因素(例如幸运加成和保底系统)也在适用范围内:购买前以数值说明其效果,并在加成生效期间实时更新显示的概率。
  • 如果完整列表无法全部显示,应通过购买前可见且标有“信息”或“详情”的控件打开列表;只有“(i)”图标而没有文字并不足够。
  • PolicyService:GetPolicyInfoForPlayerAsync() 会返回 ArePaidRandomItemsRestricted;对于受限制的玩家,请采用该页面列出的其中一种处理方式。

使用 EconomyMath.oddsPercent(outcomes) 构建概率面板,并在服务端使用 EconomyMath.pickWeighted(outcomes, rng:NextNumber()) 从同一份列表中抽取(应用任何加成后),这样显示的概率和实际概率就不会出现偏差。

常见问题

  • 第 6 次重生需要数周 → requirementGrowth 远高于乘数的增长;查看 vs prev 列,并降低 requirementGrowth,或改用乘法乘数。
  • 升级价格在约 20 级后超过收入 → 对于预期购买 50 次的升级,costGrowth 达到 1.5 以上(50 级价格约为 0 级的 6.37 亿倍);请使用 1.07-1.15。
  • 几次重生后,后期游戏失衡 → 使用乘法乘数(1.5 ^ k),却没有相匹配的需求曲线;让 requirementGrowth / q 接近你想要的比率。
  • 玩家获得了自己并未赚取的货币 → 远程调用接受金额或价格,或者只在客户端检查;发送 ID,在服务端计算价格。
  • 两次购买都通过了余额检查 → 处理程序在检查和扣款之间发生了让出;在任何 task.wait、DataStore 调用或其他让出操作之前扣款。
  • 最大购买功能导致服务端卡死 → 循环没有上限,或价格为 0;传入 maxLevel,并确保 baseCost >= 1(maxAffordable 会报错,而不是无限循环)。
  • 离线收益相当于数天的收入 → 使用了客户端时间戳、没有上限,或 lastSeen 已损坏;使用服务端时钟、设置上限,并将未来时间视为当前时间。
  • HUD 显示“1000.0K” → 在选择后缀前使用 math.floor(x * 10) / 10;请使用 formatNumber。
  • 存档失败或加载出乱码 → NaN 或无穷大进入了钱包;保存前和加载时都要清理数据。

资源

  • scripts/balance.luau — 节奏计算器:每级价格、总额、收入和等待时间;每次重生的需求、乘数、等待时间和比率;离线收益上限。请先使用 --help。
  • scripts/economy_math.luau — 纯 Luau 实现的公式、trySpend、清理函数、概率和 formatNumber;可在 Lune 和 Roblox ModuleScript 中运行。
  • scripts/test_economy_math.luau — 每个函数的测试(lune run,失败时退出码为 1)。
  • references/formulas.md — 推导过程、重生比率和示例。
  • references/server-patterns.md — 配置布局、收入计时、最大购买、重生、离线收益加载修复,以及付费随机物品抽取。

相关技能

  • roblox-luau — 服务、ModuleScript 和客户端/服务端划分。
  • roblox-networking — 远程调用验证和令牌桶速率限制。
  • roblox-datastores — 加载和保存此技能所修复的会话。
  • roblox-ui — 商店、升级和概率面板。
  • roblox-studio-workflow — Server & Clients 游戏测试。

主要参考资料

  • https://create.roblox.com/docs/production/monetization/paid-random-items
  • https://create.roblox.com/docs/scripting/events/remote
  • https://create.roblox.com/docs/scripting/security/client-server-boundary
  • https://create.roblox.com/docs/reference/engine/classes/PolicyService
  • https://create.roblox.com/docs/reference/engine/datatypes/Random
  • https://lune-org.github.io/docs

评论

支持 Markdown