godot-economy-system
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseEconomy System
游戏经济系统
Expert guidance for designing balanced game economies with currency, shops, and loot.
关于设计包含货币、商店和战利品的平衡游戏经济系统的专家指南。
NEVER Do
绝对不要做的事
- NEVER use for currency — Use
intfor small amounts, butintor custom BigInt for large economies. Integer overflow destroys economies (max 2.1B).float - NEVER forget buy/sell price spread — Selling for same price as buying creates infinite money loop. Sell price should be 30-50% of buy price.
- NEVER skip currency sinks — Without sinks (repairs, taxes, consumables), economy inflates. Players hoard unlimited wealth.
- NEVER use client-side currency validation — Client calculates "I have 1000 gold". Server validates all transactions or exploits occur.
- NEVER hardcode loot drop chances — Use Resources or JSON for loot tables. Designers need iteration without code changes.
- 绝对不要用类型存储货币 — 小额货币可以用
int,但大型经济系统应使用int或自定义BigInt类型。整数溢出会彻底破坏经济系统(float最大值为21亿)。int - 绝对不要忽略买入/卖出价差 — 买入和卖出价格相同会造成无限刷钱的漏洞。卖出价格应设为买入价格的30-50%。
- 绝对不要缺少货币消耗机制 — 没有消耗渠道(如修理费用、税费、消耗品)的话,经济会出现通胀,玩家会囤积无限财富。
- 绝对不要在客户端验证货币交易 — 客户端计算的“我有1000金币”不可信。所有交易必须由服务器验证,否则会出现漏洞利用。
- 绝对不要硬编码战利品掉落概率 — 战利品表应使用资源文件或JSON存储。设计师需要无需修改代码就能迭代调整的能力。
Available Scripts
可用脚本
MANDATORY: Read the appropriate script before implementing the corresponding pattern.
强制要求:在实现对应模式前,请先阅读相应的脚本。
loot_table_weighted.gd
loot_table_weighted.gd
Weighted loot table using cumulative probability. Resource-based design allows designer iteration via inspector without code changes.
基于累积概率的加权战利品表。基于资源的设计允许设计师通过检视面板进行迭代,无需修改代码。
Currency Manager
货币管理器
gdscript
undefinedgdscript
undefinedeconomy_manager.gd (AutoLoad)
economy_manager.gd (AutoLoad)
extends Node
signal currency_changed(old_amount: int, new_amount: int)
var gold: int = 0
func add_currency(amount: int) -> void:
var old := gold
gold += amount
currency_changed.emit(old, gold)
func spend_currency(amount: int) -> bool:
if gold < amount:
return false
var old := gold
gold -= amount
currency_changed.emit(old, gold)
return truefunc has_currency(amount: int) -> bool:
return gold >= amount
undefinedextends Node
signal currency_changed(old_amount: int, new_amount: int)
var gold: int = 0
func add_currency(amount: int) -> void:
var old := gold
gold += amount
currency_changed.emit(old, gold)
func spend_currency(amount: int) -> bool:
if gold < amount:
return false
var old := gold
gold -= amount
currency_changed.emit(old, gold)
return truefunc has_currency(amount: int) -> bool:
return gold >= amount
undefinedShop System
商店系统
gdscript
undefinedgdscript
undefinedshop_item.gd
shop_item.gd
class_name ShopItem
extends Resource
@export var item: Item
@export var buy_price: int
@export var sell_price: int
@export var stock: int = -1 # -1 = infinite
func can_buy() -> bool:
return stock != 0
```gdscriptclass_name ShopItem
extends Resource
@export var item: Item
@export var buy_price: int
@export var sell_price: int
@export var stock: int = -1 # -1 = 无限库存
func can_buy() -> bool:
return stock != 0
```gdscriptshop.gd
shop.gd
class_name Shop
extends Resource
@export var shop_name: String
@export var items: Array[ShopItem] = []
func buy_item(shop_item: ShopItem, inventory: Inventory) -> bool:
if not shop_item.can_buy():
return false
if not EconomyManager.has_currency(shop_item.buy_price):
return false
if not EconomyManager.spend_currency(shop_item.buy_price):
return false
inventory.add_item(shop_item.item, 1)
if shop_item.stock > 0:
shop_item.stock -= 1
return truefunc sell_item(item: Item, inventory: Inventory) -> bool:
# Find matching shop item for sell price
var shop_item := get_shop_item_for(item)
if not shop_item:
return false
if not inventory.has_item(item, 1):
return false
inventory.remove_item(item, 1)
EconomyManager.add_currency(shop_item.sell_price)
return truefunc get_shop_item_for(item: Item) -> ShopItem:
for shop_item in items:
if shop_item.item == item:
return shop_item
return null
undefinedclass_name Shop
extends Resource
@export var shop_name: String
@export var items: Array[ShopItem] = []
func buy_item(shop_item: ShopItem, inventory: Inventory) -> bool:
if not shop_item.can_buy():
return false
if not EconomyManager.has_currency(shop_item.buy_price):
return false
if not EconomyManager.spend_currency(shop_item.buy_price):
return false
inventory.add_item(shop_item.item, 1)
if shop_item.stock > 0:
shop_item.stock -= 1
return truefunc sell_item(item: Item, inventory: Inventory) -> bool:
# 查找对应物品的商店条目以获取卖出价格
var shop_item := get_shop_item_for(item)
if not shop_item:
return false
if not inventory.has_item(item, 1):
return false
inventory.remove_item(item, 1)
EconomyManager.add_currency(shop_item.sell_price)
return truefunc get_shop_item_for(item: Item) -> ShopItem:
for shop_item in items:
if shop_item.item == item:
return shop_item
return null
undefinedPricing Formula
定价公式
gdscript
func calculate_sell_price(buy_price: int, markup: float = 0.5) -> int:
# Sell for 50% of buy price
return int(buy_price * markup)
func calculate_dynamic_price(base_price: int, demand: float) -> int:
# Price increases with demand
return int(base_price * (1.0 + demand))gdscript
func calculate_sell_price(buy_price: int, markup: float = 0.5) -> int:
# 卖出价格为买入价格的50%
return int(buy_price * markup)
func calculate_dynamic_price(base_price: int, demand: float) -> int:
# 价格随需求增长而提高
return int(base_price * (1.0 + demand))Loot Tables
战利品表
gdscript
undefinedgdscript
undefinedloot_table.gd
loot_table.gd
class_name LootTable
extends Resource
@export var drops: Array[LootDrop] = []
func roll_loot() -> Array[Item]:
var items: Array[Item] = []
for drop in drops:
if randf() < drop.chance:
items.append(drop.item)
return items
```gdscriptclass_name LootTable
extends Resource
@export var drops: Array[LootDrop] = []
func roll_loot() -> Array[Item]:
var items: Array[Item] = []
for drop in drops:
if randf() < drop.chance:
items.append(drop.item)
return items
```gdscriptloot_drop.gd
loot_drop.gd
class_name LootDrop
extends Resource
@export var item: Item
@export var chance: float = 0.5
@export var min_amount: int = 1
@export var max_amount: int = 1
undefinedclass_name LootDrop
extends Resource
@export var item: Item
@export var chance: float = 0.5
@export var min_amount: int = 1
@export var max_amount: int = 1
undefinedBest Practices
最佳实践
- Balance - Test economy carefully
- Sinks - Provide money sinks (repairs, etc.)
- Inflation - Control money generation
- 平衡性 - 仔细测试经济系统
- 消耗机制 - 提供货币消耗渠道(如修理费用等)
- 通胀控制 - 管控货币产出量
Reference
参考资料
- Related: ,
godot-inventory-systemgodot-save-load-systems
- 相关资源:,
godot-inventory-systemgodot-save-load-systems
Related
相关内容
- Master Skill: godot-master
- 核心技能:godot-master