SuperAPI AI 工具集

bevy-ability-system

编程与开发

查看项目

更新于 10-16 06:08

技能介绍

用途

本技能用于在 Bevy 引擎中实现角色能力(ability)系统,处理能力的授予、冷却与消耗。当某个角色需要授予、冷却或消耗一项能力时加载本技能。战斗结算不属于本技能范围,仍由 bevy-combat-system 负责。

主要能力

  • 能力定义:通过一个 Resource 目录(catalog)加施法者身上的组件行来表示。
  • 冷却:在 FixedUpdate 中使用 Time<Fixed>::delta_secs 递减剩余冷却时间。
  • 施放:在冷却与充能门槛通过后,通过 MessageWriter<CastAccepted> 发出消息。
  • 充能:冷却结束且未达上限时恢复充能次数。
  • 全局冷却:共享锁放在 Resource 中,由单一系统持有。
  • 状态效果叠加:作为组件列表在 FixedUpdate 中逐帧推进。

ECS 结构

  • 组件:施法者身上的能力 id、充能次数、剩余冷却时间。
  • 资源:全局范围的表存放在 Resource 中(参见 bevy-data-resources)。
  • 系统:在 Update 或固定时间步上修改这些组件;当伤害必须先于死亡结算时使用 .chain()。
  • 消息:一次性事实(命中、拾取、任务推进)通过 bevy-events-messaging 传递;本文件不新增事件类型名称。

使用方式

示例依赖:

[package]
name = "abilities"
version = "0.1.0"
edition = "2021"

[dependencies]
bevy = "0.20"

冷却与充能共享施法者,在 FixedUpdate 上先推进再接受施放:

#[derive(Component)]
struct Cooldown {
    remaining: f32,
    duration: f32,
}

#[derive(Component)]
struct Charges {
    current: u32,
    max: u32,
}

#[derive(Message)]
struct CastAccepted {
    caster: Entity,
}

fn tick_cooldowns(time: Res<Time<Fixed>>, mut query: Query<&mut Cooldown>) {
    let dt = time.delta_secs();
    for mut cooldown in &mut query {
        cooldown.remaining = (cooldown.remaining - dt).max(0.0);
    }
}

fn try_cast(
    mut casters: Query<(Entity, &mut Cooldown, &mut Charges)>,
    mut casts: MessageWriter<CastAccepted>,
) {
    for (entity, mut cooldown, mut charges) in &mut casters {
        if cooldown.remaining > 0.0 || charges.current == 0 {
            continue;
        }
        charges.current -= 1;
        cooldown.remaining = cooldown.duration;
        casts.write(CastAccepted { caster: entity });
    }
}

fn recharge(time: Res<Time<Fixed>>, mut casters: Query<(&Cooldown, &mut Charges)>) {
    let dt = time.delta_secs();
    for (cooldown, mut charges) in &mut casters {
        if cooldown.remaining <= 0.0 && charges.current < charges.max && dt > 0.0 {
            charges.current += 1;
        }
    }
}

pub struct AbilityPlugin;

impl Plugin for AbilityPlugin {
    fn build(&self, app: &mut App) {
        app.add_message::<CastAccepted>()
            .add_systems(FixedUpdate, (tick_cooldowns, try_cast, recharge).chain());
    }
}

目录是一个资源,实时冷却保留在实体上:

#[derive(Clone, Copy)]
struct AbilityDef {
    id: u32,
    cooldown: f32,
    cost: u32,
}

#[derive(Resource)]
struct AbilityCatalog {
    rows: Vec<AbilityDef>,
}

fn lookup(catalog: &AbilityCatalog, id: u32) -> Option<&AbilityDef> {
    catalog.rows.iter().find(|row| row.id == id)
}

#[derive(Component)]
struct Cooldown {
    remaining: f32,
    duration: f32,
}

#[derive(Component)]
struct Charges {
    current: u32,
    max: u32,
}

fn spawn_caster(mut commands: Commands, catalog: Res<AbilityCatalog>) {
    let def = lookup(&catalog, 1);
    let duration = def.map(|row| row.cooldown).unwrap_or(0.5);
    commands.spawn((
        Cooldown {
            remaining: 0.0,
            duration,
        },
        Charges { current: 2, max: 2 },
    ));
}

共享锁放在资源中,由单一系统持有:

#[derive(Message)]
struct CastAccepted {
    caster: Entity,
}

#[derive(Resource)]
struct GlobalCooldown {
    remaining: f32,
}

fn tick_gcd(time: Res<Time<Fixed>>, mut gcd: ResMut<GlobalCooldown>) {
    gcd.remaining = (gcd.remaining - time.delta_secs()).max(0.0);
}

fn arm_gcd(mut gcd: ResMut<GlobalCooldown>, mut casts: MessageReader<CastAccepted>) {
    for _cast in casts.read() {
        gcd.remaining = gcd.remaining.max(0.4);
    }
}

在添加 tick_gcd 与 arm_gcd 的同一插件中,用 add_message 注册 CastAccepted。

状态归属

部分 归属 谁可修改 调度
单个实体上的数据 Component 一个系统通过 Query Update 或 FixedMain
整个应用的一个值 Resource 一个系统 Startup 插入,之后由读取它的调度
生成 Commands 生成系统 初始世界用 Startup;运行时生成用之后的调度
不可竞态的顺序 .chain() 仅被链式连接的系统 同一调度
插件边界 Plugin build 注册系统与资源 应用运行前

借用规则:两个都可变查询同一组件的系统必须排序(.chain())或拆分,使只有一个写入。无关系统保持并行。

决策指引

如果你需要 这样做 不要
每实体数据 Component + Query 把值存在实体之外
应用级配置或时钟 Resource 把值复制到每个实体
稳定模拟步长 FixedMain 与 Fixed 时钟 把模拟绑定到原始帧 Update
启动生成 Startup 中的 Commands 从渲染系统生成
非共享状态的跨系统通知 bevy-events-messaging 中的 Message 或 observer 槽位 在本文件中发明新事件类型
文档集之外的 API 先查官方文档 编造的 crate 或 API

适用场景

  • 需要为角色实现冷却、充能、能力目录的游戏项目。
  • 使用 Bevy 0.20+ 与 ECS 架构的项目。
  • 需要全局冷却或状态效果叠加的能力系统。

限制与禁止事项

  • 不要在文档 URL 中固定 /0.20.0/;链接保持最新,0.20 目标只在正文中说明一次。
  • 不要从两个未排序的系统可变查询同一组件。
  • 不要在此发明物理、导航、网络或 XR crate。
  • 不要把冷却存储在进程级全局静态中。
  • 不要使用编造的 API 或未命名的第三方 crate 作为求解方案。

相关技能

前置:bevy-master(枢纽与调度)、bevy-ecs-composition(组件与系统)、bevy-combat-system(命中结算)、bevy-input-handling(施放输入)、bevy-data-resources(表与定义)、bevy-events-messaging(一次性事实)。

补充:bevy-state-machines(模式标志)。

下游/消费者:暂无。

主技能:bevy-master(Bevy 路由)。