用途
本技能用于在 Bevy ECS 中处理钱包、价格与商人库存相关的数值变化。当钱包、价格或商人库存的数字需要变动时加载本技能。物品身份(item identity)仍由 bevy-inventory-system 负责,本技能不处理物品堆叠本身。
主要能力
- 钱包:以组件(Component)形式保存你自定义的货币金额。
- 价格行:价格行集中存放在一个资源(Resource)中,即 PriceTable(价格表)。
- 系统:在 Update 中修改钱包。当库存必须在钱包扣款之前下降时,使用 .chain() 排序。
- 消息:购买或转账以消息形式表达,本技能命名为 Purchase 和 Transfer。
- 商人库存:Vendor 组件记录物品 id 与库存数量,购买消息只携带物品 id,库存系统只负责拒绝空货架。
惯用写法(ECS 形态)
| 需求 | Bevy 形态 |
|---|---|
| 钱包 | 一个由你定义货币金额的组件 |
| 价格行 | 一个资源表 |
| 交易 | 一条消息;一个系统用 get_many_mut 同时写入两个钱包 |
范围
- 金币存放在钱包组件上。
- 价格存放在一个资源中。
- 购买消息是买方钱包的唯一写入者。
- 钱包的持久化属于 bevy-save-load 的职责。
使用方式(示例)
Cargo 依赖:
[package]
name = "economy"
version = "0.1.0"
edition = "2021"
[dependencies]
bevy = "0.20"
价格查找与钱包写入共享同一条链,使扣款能看到被选中的价格行:
#[derive(Component)]
struct Wallet {
coins: u32,
}
#[derive(Clone, Copy)]
struct PriceRow {
item: u32,
cost: u32,
}
#[derive(Resource)]
struct PriceTable {
rows: Vec<PriceRow>,
}
#[derive(Message)]
struct Purchase {
buyer: Entity,
item: u32,
}
fn buy(
mut purchases: MessageReader<Purchase>,
table: Res<PriceTable>,
mut wallets: Query<&mut Wallet>,
) {
for purchase in purchases.read() {
let Some(row) = table.rows.iter().find(|row| row.item == purchase.item) else {
continue;
};
let Ok(mut wallet) = wallets.get_mut(purchase.buyer) else {
continue;
};
if wallet.coins < row.cost {
continue;
}
wallet.coins -= row.cost;
}
}
pub struct EconomyPlugin;
impl Plugin for EconomyPlugin {
fn build(&self, app: &mut App) {
app.insert_resource(PriceTable {
rows: vec![
PriceRow { item: 1, cost: 12 },
PriceRow { item: 2, cost: 40 },
],
})
.add_message::<Purchase>()
.add_systems(Update, buy);
}
}
在两个钱包之间转移金币使用单个可变查询,使两次写入不会竞争:
#[derive(Component)]
struct Wallet {
coins: u32,
}
#[derive(Message)]
struct Transfer {
from: Entity,
to: Entity,
amount: u32,
}
fn transfer(mut moves: MessageReader<Transfer>, mut wallets: Query<&mut Wallet>) {
for mv in moves.read() {
if mv.amount == 0 || mv.from == mv.to {
continue;
}
let Ok([mut from, mut to]) = wallets.get_many_mut([mv.from, mv.to]) else {
continue;
};
if from.coins < mv.amount {
continue;
}
from.coins -= mv.amount;
to.coins += mv.amount;
}
}
商人列出库存。购买消息携带物品 id;该系统只拒绝空货架:
#[derive(Component)]
struct Vendor {
item: u32,
stock: u32,
}
#[derive(Message)]
struct Purchase {
buyer: Entity,
item: u32,
}
fn take_stock(mut purchases: MessageReader<Purchase>, mut vendors: Query<&mut Vendor>) {
for purchase in purchases.read() {
for mut vendor in &mut vendors {
if vendor.item != purchase.item || vendor.stock == 0 {
continue;
}
vendor.stock -= 1;
break;
}
}
}
当一次销售必须同时减少货架与钱包时,将 take_stock 排在 buy 之前(使用 .chain())。
专家知识要点
目标版本:Bevy 0.20+。
核心 ECS 类型:Component、Resource、Query、Commands、Startup、Update、Fixed / FixedMain(bevy::time)、.chain()、Plugin、DefaultPlugins、MinimalPlugins。消息与观察者属于所有权槽位,其 API 见 bevy-events-messaging。除非用 .chain() 对冲突系统排序,否则系统并行运行。
状态归属:
| 部分 | 归属 | 谁可修改 | 调度 |
|---|---|---|---|
| 单个实体上的数据 | Component | 一个系统通过 Query | Update 或 FixedMain |
| 整个应用的一个值 | Resource | 一个系统 | Startup 插入,之后由读取它的调度使用 |
| 生成 | Commands | 执行生成的系统 | 初始世界用 Startup;运行时生成用后续调度 |
| 不能竞争的顺序 | .chain() | 仅被链式的系统 | 同一调度 |
| 插件边界 | Plugin | build 注册系统与资源 | 应用运行之前 |
借用规则:两个都可变查询同一组件的系统必须排序(.chain()),或拆分使只有一个写入。不相关的系统保持并行。这是 ECS 页面规则,不是对 system-set API 的猜测。
决策表:
| 如果你需要 | 这样做 | 不要 |
|---|---|---|
| 每实体数据 | Component + Query | 在角色上挂场景树脚本 |
| 应用级配置或时钟 | Resource | 把值复制到每个实体 |
| 稳定的模拟步长 | FixedMain 与 Fixed 时钟 | 把模拟绑定到原始帧 Update |
| 启动生成 | Startup 中的 Commands | 从渲染系统生成 |
| 非共享状态的跨系统通知 | bevy-events-messaging 中的消息或观察者槽位 | 在本文件中新造事件类型 |
| 文档集合之外的 API | 阅读下方链接的官方手册 | 编造的 crate 或 API |
所有权表见 references/ecs-ownership.md。
禁止事项
- 不要在文档 URL 中固定 /0.20.0/。原因:链接保持指向最新版;0.20 目标只在正文中声明一次。
- 不要从两个未排序的系统可变查询同一组件。原因:除非 .chain() 排序,调度会并行运行系统。
- 不要在此处发明物理、导航、网络或 XR crate。原因:本技能只命名有文档的 Bevy crate 与模块。
- 本机制不使用场景树节点或信号总线。原因:Bevy 代码保持惯用 ECS,只使用有文档的 Bevy API。
- 不要发明 API 或把未命名的第三方 crate 作为选定求解器。原因:Bevy 代码保持惯用 ECS,只使用有文档的 Bevy API。
参考
bevy-master 上的库固定版本保持 0.20。
官方文档:
- Assets - 官方资源目录。未选择第三方 crate。
- Examples - 最新分支上的示例树。
- ECS - Component、systems、Query、Startup、Update 与 .chain()。
- Plugins - Plugin、DefaultPlugins、MinimalPlugins 与 add_plugins。
相关技能
前置:
- bevy-master - 中枢与调度。
- bevy-ecs-composition - 组件与系统。
- bevy-inventory-system - 物品堆叠。
- bevy-save-load - 持久化钱包。
- bevy-data-resources - 表与定义。
- bevy-events-messaging - 一次性事实。
补充:
- bevy-state-machines - 模式标志。
下游 / 消费者:暂无。
主技能:bevy-master - Bevy 路由。