软货币不是数字越大越有成长感
金币、木材、经验、能量、碎片,这些软货币是很多 Phaser 游戏的长期循环核心。玩家打怪获得金币,用金币升级;完成任务获得材料,用材料合成;离线获得收益,用收益扩建。若产出和消耗没有规划,经济很快会失衡:前期缺到卡死,中期刚好,后期金币多到没有意义;活动奖励一发,主线价格全崩;客户端展示写着需要 1000 金币,实际扣了 1200;玩家断网重试导致重复扣费。经济系统看似数值设计,客户端也承担很大责任。
客户端不应该成为经济权威,尤其是有账号、排行榜、付费或运营活动时。Phaser 客户端负责展示余额、预览价格、播放获得和消耗动画、提交购买请求、处理失败恢复。真正扣钱和发货最好由服务端或统一 EconomyService 完成。即使纯单机,也要把经济操作做成账本式事务,避免 UI 直接改数字。
产出和消耗要成对设计
软货币需要来源和消耗。来源包括关卡奖励、任务、离线收益、邮件、活动、出售物品。消耗包括升级、购买、合成、刷新、复活、装饰、加速。只增加来源不增加消耗,会通胀;只增加消耗不增加来源,会卡进度。经济表应该按玩家阶段列出每小时产出、关键消耗、预期余额。客户端至少要知道这些操作的类型和来源,方便日志和展示。
消耗也要分健康消耗和惩罚消耗。升级、装饰、收藏是玩家愿意花的;失败罚款、强制修理、频繁刷新可能让玩家反感。客户端文案和反馈要让消耗显得合理。比如升级按钮展示提升效果,刷新商店展示可获得机会,修理展示恢复收益。不要只弹“金币不足”。
flowchart TD
A["RewardSource:关卡、任务、离线、邮件"] --> B["EconomyLedger:收入记录"]
C["SpendAction:升级、购买、合成、刷新"] --> D["PriceResolver:价格曲线和折扣"]
D --> E["AffordabilityCheck:余额、限制、活动"]
E --> F["TransactionService:扣费和发货"]
F --> G["BalanceStore:余额更新"]
G --> H["Phaser UI:余额动画、按钮状态、缺口提示"]
F --> I["EconomyLog:source、sink、version"]
价格曲线要可解释
升级价格常见公式是指数增长、分段增长或表格配置。指数曲线容易后期爆炸,线性曲线后期可能太便宜。可以用分段表:前 10 级教学便宜,10 到 30 级稳定增长,30 级后引入新货币或材料。关键是价格曲线要能被画出来。不要把价格散落在代码里,否则平衡时看不到长期趋势。
客户端展示价格时要显示当前价格和下一次变化。比如“升级到 12 级:1200 金币,攻击 +15”。若有折扣,显示原价和折后价,并说明来源。价格预览和实际扣费必须同源。活动折扣、VIP 折扣、首购折扣叠加时,PriceResolver 输出最终价格和拆解,UI 只展示结果。
余额变化要有账本
玩家最敏感的是“钱去哪了”。每次收入和支出都应该有记录:时间、货币、数量、来源、操作 id、配置版本。客户端至少保留最近记录,服务端保留完整账本。出现投诉时,可以追踪“04-28 10:31 升级弓塔扣 1200 金币”。没有账本,客服只能靠猜。
本地表现上,余额动画要跟真实结果一致。购买请求未确认时,不要先永久扣余额。可以做乐观预览,但失败后必须回滚并提示。大额消费最好二次确认,尤其是不可撤销操作。小额高频消费可以省确认,但要有防连点。
一个价格解析器
下面的代码展示表格价格和折扣拆解。真实项目中,货币类型和折扣来源会更多。
interface Price {
currency: "gold" | "wood" | "gem";
amount: number;
}
interface Discount {
id: string;
multiplier: number;
}
export function resolvePrice(base: Price, discounts: Discount[]) {
let multiplier = 1;
for (const discount of discounts) multiplier *= discount.multiplier;
const finalAmount = Math.max(0, Math.floor(base.amount * multiplier));
return {
base,
discounts,
final: { currency: base.currency, amount: finalAmount },
};
}
这段代码返回拆解,而不只是最终数字。UI 可以显示折扣来源,日志可以记录折扣版本。价格相关问题最怕黑箱,拆解能减少大量误解。
货币不足时给路径
“金币不足”不是好提示。玩家需要知道差多少、哪里能获得、是否有替代方案。按钮可以显示“还差 240 金币”,点击后打开推荐来源:去打某关、领取离线收益、出售多余材料、完成任务。不要直接把玩家推向付费,软货币的缺口提示应服务玩法循环。
如果有多货币,缺口提示更要谨慎。比如升级需要金币和木材,金币够木材不够,按钮应突出木材缺口。材料来自不同系统时,来源提示要准确。客户端可以从配置中读取货币来源,不要手写死链接。
防通胀和消耗池
长期游戏需要消耗池。一次性升级消耗在满级后会消失,后期货币会堆积。可持续消耗包括装饰、外观、刷新、捐赠、排行榜报名、随机商店、维护费用。但消耗池不能都变成强制税。最健康的是自愿型消耗:玩家为了效率、表达或收集花钱,而不是被惩罚。
客户端要帮助玩家理解这些消耗的价值。装饰能展示预览,刷新能显示可能商品,捐赠能显示公共进度。若消耗没有反馈,玩家会觉得货币被吞。Phaser 的动画和 UI 可以把经济操作做得有仪式感,但前提是规则公平。
服务端权威和离线模式
有服务端时,余额以服务端为准。客户端本地余额只是缓存。购买时发送 actionId、priceVersion、客户端看到的价格,服务端重新计算并返回结果。若价格过期,服务端拒绝或按旧价保护,规则要明确。客户端收到拒绝后刷新余额和价格,不要继续显示旧状态。
纯单机时,也建议有 TransactionService。每次操作生成 transactionId,先检查余额,再应用结果,再保存。保存失败则回滚或提示。不要让 UI 按钮直接 gold -= price。本地经济也需要一致性。
上线前检查清单
确认收入和支出都有来源类型;确认价格曲线来自配置或可视化表;确认价格预览和实际扣费同源;确认余额变化有账本;确认购买请求幂等并防连点;确认货币不足提示差额和来源;确认折扣有拆解和版本;确认后期有健康消耗池;确认服务端重新计算关键价格;确认客户端失败后能刷新和回滚。
软货币经济的核心是信任。Phaser 可以把金币飞行动画做得很舒服,但玩家真正关心的是数字是否公平、消耗是否值得、失败是否能恢复。把经济操作当成交易,而不是 UI 数字变化,长期循环才站得住。
多货币之间要避免互相踩踏
很多游戏不止一种软货币。金币用于基础升级,木材用于建筑,徽章用于活动,碎片用于角色。多货币能让循环更丰富,但也容易让玩家困惑。每种货币应有清晰用途和来源。若金币和木材都能买同一升级,玩家会只选择更容易获得的一种,另一种失去价值。若每个系统都发自己的货币,背包会膨胀。
客户端展示要帮助玩家理解货币层级。常用货币放在 HUD,低频货币放在对应系统内,活动货币只在活动页突出。不要把十几种货币全部堆在顶部栏。货币不足提示也应跳转到对应来源,而不是打开一个通用商店。
活动奖励对主经济的冲击
运营活动常常是经济失衡来源。一次登录送大量金币,可能让新手跳过前期升级节奏;活动商店低价卖高级材料,可能让合成系统失去意义。活动奖励应进入经济预测表。客户端至少要按 rewardSource 记录活动产出,方便分析活动后玩家余额变化。
活动货币可以隔离主经济,但也要有回收。活动结束后,剩余活动币是清零、兑换金币还是保留到下次?规则要提前展示。若自动兑换,客户端在活动结束时显示兑换结果或通过邮件发放。不要让玩家发现活动币突然消失。
价格显示和心理阈值
价格不仅是数学,也影响感受。999 和 1000 在视觉上不同,升级价格连续跳涨会让玩家停下。客户端展示可以使用缩写,但关键消费要显示完整数字。比如 HUD 可以显示 1.2M,确认弹窗显示 1,234,500。不要在扣费确认里用模糊缩写,玩家需要清楚知道要花多少。
大额消费最好展示购买后余额。比如“花费 50,000 金币,剩余 12,340”。这能减少误触和后悔。若消费会影响后续系统,比如升级后维修费增加,也要在详情里说明。经济 UI 的透明度会直接影响玩家信任。
异常检测和经济报警
客户端和服务端都应关注异常:短时间大量收入、负余额、价格为 0、重复交易、余额跳变。客户端可以本地断言,不允许余额显示负数;服务端做权威报警。纯单机也要防止存档损坏导致余额 NaN 或无限。显示层遇到异常值时,不要继续渲染成奇怪文本,应回退并提示存档异常。
经济日志可以定期汇总:每个来源产出多少,每个消耗池消耗多少,玩家各阶段平均余额。没有这些数据,经济调优只能靠感觉。Phaser 客户端不是分析后台,但它负责产生正确、带来源的事件。
新手期经济保护
新手期最怕玩家把关键货币花错。可以在前几次大额消费时增加确认,或者限制某些消耗入口直到玩家理解系统。比如升级主武器前,不开放随机刷新商店;教学合成材料使用专用材料,不消耗稀缺资源。保护不是不给自由,而是避免第一次体验就进入负反馈。
同时,新手奖励要克制。给太多金币会让早期升级失去意义,给太少又卡住节奏。可以用“指定用途奖励”,例如只可用于第一次升级的训练币。客户端展示时明确它的用途,避免玩家以为这是通用货币。
经济 UI 的状态一致性
余额通常出现在多个地方:HUD、商店、背包、升级页、结算页。它们必须订阅同一 BalanceStore。交易完成后,所有可见位置同时刷新。不要商店里余额减少了,HUD 还显示旧值。余额动画可以延迟,但底层状态要立即一致。若为了动画延迟显示,也要避免玩家在延迟期间再次购买造成误判。
价格按钮也要实时更新。余额不足时灰掉,余额刚好够时可点,折扣变化时刷新。弱网下按钮进入 pending,防止重复点击。经济 UI 的稳定性会直接影响玩家对系统的信任,比复杂动画更重要。
货币回滚和补偿
经济配置难免会出错。价格写错、奖励翻倍、活动重复发放,都需要回滚或补偿策略。客户端要能展示补偿邮件、价格修正说明和余额刷新提示。不要静默扣回玩家货币,这会严重损害信任。若必须修正异常收益,也要给出可解释记录。
补偿也要进入账本。来源写成 economy_fix,附带原因和版本。这样未来分析余额时,不会把补偿误认为正常产出。经济系统越透明,事故恢复越平稳。
经济配置的发布流程
价格和奖励配置不应直接改线上。发布前先在测试环境跑一组模拟:新玩家第一小时能否完成关键升级,中期玩家日常产出是否覆盖基础消耗,后期玩家是否还有消耗目标。模拟结果和上一版本对比,差异过大就需要人工确认。客户端可以显示 economyConfigVersion,方便测试和客服确认玩家当前使用哪套价格。
配置回滚也要准备。若某次价格发布错误,客户端拉到新配置后应能接受服务端回滚,不把旧价格缓存到永久。交易请求带上价格版本,服务端发现版本过期时返回刷新指令。这样价格事故能快速止血。
回滚后 UI 要刷新所有价格,不要让旧弹窗继续提交过期交易。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。