SuperAPI AI 工具集

bevy-genre-rts

编程与开发

查看项目

更新于 10-16 06:08

技能介绍

用途

bevy-genre-rts 是一个 Bevy 0.20 的 RTS 类型路由技能,目标是在 ECS 架构下统一处理即时战略游戏的选择、移动指令和控制编组三类核心逻辑。它本身是一个"薄路由",实际的领域实现分散在多个 Bevy 技能中,由它负责调度与整合。当项目需要处理选择(selection)、指令(orders)和编组(groups)时加载此技能。

ECS 结构与主要能力

该技能把 RTS 玩法数据落在两个位置上:

  • 组件(Component):承载每个实体上的类型标记与数据,例如选中状态、移动指令。此技能不引入新的引擎类型。
  • 资源(Resource):持有整个运行范围内共享的计数器(分数、波次索引、随机种子等),通过 bevy-data-resources 实现。

系统在 Update 或来自 bevy-master 的固定时间步上读取这些组件;当后续系统必须看到前一步结果时,用 .chain() 排序。游戏模式切换通过 bevy-state-machines 处理,不自行发明类型插件。

核心能力示例:

  • 选择:Selected 标记当前组;点击选择通过由其他系统填充的指针资源完成,半径内的单位获得 Selected。
  • 移动指令:MoveOrder 记录目标点,行军系统在指令写入后执行。
  • 控制编组:数字键把选中实体存入资源,再次按键清除 Selected 并恢复该编组。

使用方式

示例采用 Bevy 0.20,依赖声明为:

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

[dependencies]
bevy = "0.20"

选择标记与移动指令均以组件表示:

#[derive(Component)]
struct Selected;

#[derive(Component)]
struct MoveOrder {
    target: Vec3,
}

下达移动指令与执行行军通过 .chain() 在 FixedUpdate 中排序:

fn issue_move(keys: Res<ButtonInput<KeyCode>>, mut units: Query<&mut MoveOrder, With<Selected>>) {
    if !keys.just_pressed(KeyCode::KeyM) {
        return;
    }
    for mut order in &mut units {
        order.target = Vec3::new(12.0, 0.0, 6.0);
    }
}

fn march(time: Res<Time<Fixed>>, mut units: Query<(&MoveOrder, &mut Transform)>) {
    let dt = time.delta_secs();
    for (order, mut transform) in &mut units {
        let delta = order.target - transform.translation;
        let step = 6.0 * dt;
        if delta.length() <= step {
            transform.translation = order.target;
        } else {
            transform.translation += delta.normalize_or_zero() * step;
        }
    }
}

pub struct OrderPlugin;

impl Plugin for OrderPlugin {
    fn build(&self, app: &mut App) {
        app.add_systems(FixedUpdate, (issue_move, march).chain());
    }
}

控制编组以一个资源持有成员实体列表,数字键用于绑定与恢复:

#[derive(Resource, Default)]
struct ControlGroup {
    members: Vec<Entity>,
}

#[derive(Component)]
struct Selected;

fn bind_group(
    keys: Res<ButtonInput<KeyCode>>,
    selected: Query<Entity, With<Selected>>,
    mut group: ResMut<ControlGroup>,
    mut commands: Commands,
) {
    if keys.just_pressed(KeyCode::Digit1) && keys.pressed(KeyCode::ControlLeft) {
        group.members.clear();
        for entity in &selected {
            group.members.push(entity);
        }
        return;
    }
    if keys.just_pressed(KeyCode::Digit1) {
        for entity in &selected {
            commands.entity(entity).remove::<Selected>();
        }
        for entity in group.members.clone() {
            commands.entity(entity).insert(Selected);
        }
    }
}

点击选择基于指针资源与半径判定:

#[derive(Resource)]
struct PointerWorld(Vec3);

#[derive(Component)]
struct Selectable;

#[derive(Component)]
struct Selected;

fn click_select(
    buttons: Res<ButtonInput<MouseButton>>,
    pointer: Res<PointerWorld>,
    mut commands: Commands,
    units: Query<(Entity, &Transform), With<Selectable>>,
    selected: Query<Entity, With<Selected>>,
) {
    if !buttons.just_pressed(MouseButton::Left) {
        return;
    }
    for entity in &selected {
        commands.entity(entity).remove::<Selected>();
    }
    for (entity, transform) in &units {
        if transform.translation.distance(pointer.0) < 1.5 {
            commands.entity(entity).insert(Selected);
        }
    }
}

fn spawn_units(mut commands: Commands) {
    commands.insert_resource(PointerWorld(Vec3::ZERO));
    for index in 0..4 {
        commands.spawn((
            Selectable,
            MoveOrder {
                target: Vec3::new(index as f32 * 2.0, 0.0, 0.0),
            },
            Transform::from_xyz(index as f32 * 2.0, 0.0, 0.0),
        ));
    }
}

路由关系

  • bevy-input-handling:选择点击。
  • bevy-ai-navigation:移动指令与导航(寻路保留在此)。
  • bevy-combat-system:攻击。
  • bevy-economy-system:成本。

适用场景

  • 需要在 Bevy 0.20 下搭建 RTS 选择、编组、移动指令与行军逻辑的项目。
  • 希望以纯 ECS 方式(组件 + 资源 + 调度排序)组织 RTS 数据的项目。

限制与约束

  • 目标版本为 Bevy 0.20+。文档 URL 不固定到 /0.20.0/,链接保持在最新版,版本目标只在正文中说明一次。
  • 不要从两个无序系统中可变查询同一组件;因为除非用 .chain() 排序,调度会并行运行系统。
  • 不在此引入物理、导航、网络或 XR crate;只命名有文档的 Bevy crate 与模块。
  • Bevy 代码中不使用场景树类型,保持惯用 ECS,只使用有文档的 Bevy API。
  • 不发明类型 API;不在此挑选物理或网络 crate。
  • 关于事件与观察者(消息/观察者)的 API 属于 bevy-events-messaging 负责的范畴,本技能不新建事件类型。
  • 编组指令方式为:每个单位上挂 Selected 与 MoveOrder,在同一系统中行军;不要把阵型发明为引擎单例。

相关技能

  • 前置:bevy-master(ECS 所有权与调度)、bevy-ecs-composition(生成与查询形态)。
  • 补充:bevy-input-handling、bevy-ai-navigation、bevy-combat-system、bevy-economy-system。
  • 下游/消费方:无,此路由不拥有第二实现。
  • 主路由:bevy-master。