用途
当角色需要执行追逐(chase)、巡逻(patrol)或等待(wait)行为时,可加载本技能。它负责决策意图和期望速度(DesiredVelocity),不负责路径计算、Transform 移动或视线检测。
主要能力
- 用枚举组件(Brain)表示行为模式:Wait、Patrol、Chase。
- 用 Goal 组件保存目标位置,用 DesiredVelocity 组件保存期望速度。
- 用 RetargetClock 计时器资源在 FixedUpdate 上节流重定向频率。
- 用 PatrolRoute 资源保存巡逻路径点。
- 通过 .chain() 保证策略系统先于移动系统运行。
使用方式
ECS 结构:
- 组件:模式标志可用枚举 Component;目标位置可用自定义组件。
- 资源:共享巡逻表可定义为 Resource。
- 系统:读取模式并写入期望速度或路径点,运行在 Update 或 Fixed 上,使用 .chain() 让策略先于移动运行。不要调用会写 Transform 的 agent 回调。
- 调度:当结果要喂给移动步骤时,使用 Fixed / FixedMain。
策略映射:
- 追逐 vs 巡逻 vs 等待:枚举 Component 加一个写 Goal 的系统。
- 重定向节流:Timer 资源在 FixedUpdate 上 tick。
- 人群与避让:由 bevy-navigation 负责。
- 烘焙与障碍物:由 bevy-navigation 负责。
- 视线:由 bevy-spatial-queries 负责。
策略写入 DesiredVelocity,不移动 Transform,也不查询导航网格。
依赖:
[dependencies]
bevy = "0.20"
示例代码:
#[derive(Clone, Copy, PartialEq, Eq, Component)]
enum Brain {
Wait,
Patrol,
Chase,
}
#[derive(Component)]
struct WaypointIndex(usize);
#[derive(Component)]
struct Goal(Vec3);
#[derive(Component)]
struct DesiredVelocity(Vec3);
#[derive(Component)]
struct Player;
#[derive(Resource)]
struct PatrolRoute {
points: Vec<Vec3>,
}
#[derive(Resource)]
struct RetargetClock(Timer);
fn tick_policy(
time: Res<Time>,
mut clock: ResMut<RetargetClock>,
route: Res<PatrolRoute>,
players: Query<&Transform, With<Player>>,
mut actors: Query<(&Brain, &Transform, &mut WaypointIndex, &mut Goal)>,
) {
clock.0.tick(time.delta());
if !clock.0.just_finished() {
return;
}
let player_pos = players.iter().next().map(|transform| transform.translation);
for (brain, transform, mut cursor, mut goal) in &mut actors {
match *brain {
Brain::Wait => goal.0 = transform.translation,
Brain::Patrol => {
if route.points.is_empty() {
continue;
}
cursor.0 = (cursor.0 + 1) % route.points.len();
goal.0 = route.points[cursor.0];
}
Brain::Chase => {
if let Some(pos) = player_pos {
goal.0 = pos;
}
}
}
}
}
fn steer(mut actors: Query<(&Transform, &Goal, &mut DesiredVelocity), With<Brain>>) {
for (transform, goal, mut velocity) in &mut actors {
let offset = goal.0 - transform.translation;
let flat = Vec3::new(offset.x, 0.0, offset.z);
velocity.0 = if flat.length_squared() < 0.05 {
Vec3::ZERO
} else {
flat.normalize() * 3.0
};
}
}
pub struct NavPolicyPlugin;
impl Plugin for NavPolicyPlugin {
fn build(&self, app: &mut App) {
app.insert_resource(PatrolRoute {
points: vec![Vec3::new(-6.0, 0.0, 0.0), Vec3::new(6.0, 0.0, 4.0)],
})
.insert_resource(RetargetClock(Timer::from_seconds(
0.4,
TimerMode::Repeating,
)))
.add_systems(FixedUpdate, (tick_policy, steer).chain());
}
}
#[derive(Component)]
struct PatrolAgent;
fn spawn_patrol(mut commands: Commands) {
commands.spawn((
PatrolAgent,
Transform::from_xyz(0.0, 0.0, 0.0),
DesiredDir(Vec3::X),
));
}
#[derive(Component)]
struct DesiredDir(Vec3);
fn hold_when_close(mut agents: Query<(&Transform, &mut DesiredDir), With<PatrolAgent>>) {
for (transform, mut desired) in &mut agents {
if transform.translation.distance(Vec3::ZERO) < 0.5 {
desired.0 = Vec3::ZERO;
}
}
}
适用场景
- 需要让角色在追逐、巡逻、等待之间切换的游戏 AI。
- 需要将决策意图与路径计算、移动、感知解耦的 Bevy 项目。
限制
- 目标版本为 Bevy 0.20+。
- 本技能只写入 Goal 和 DesiredVelocity,不移动 Transform,不查询导航网格。
- 路径与导航网格由 bevy-navigation 负责;Transform 集成由 bevy-character-movement 负责;视线传感器由 bevy-spatial-queries 负责。
- 不要在文档 URL 中固定 /0.20.0/。
- 不要从两个无序系统可变查询同一组件;调度默认并行运行系统,除非用 .chain() 排序。
- 不要在本技能中发明物理、导航、网络或 XR crate。
- 不要使用其他引擎的 navigation-agent 或 nav-server 类型。
- 不要使用未命名的第三方导航或物理 crate。
- 不要发明路径、烘焙或避让 API。
- 应用状态不是逐实体巡逻模式;逐实体标志应保持为组件(见 bevy-state-machines)。
相关技能
前置:bevy-master(ECS 所有权)、bevy-navigation(路径与导航网格)、bevy-state-machines(模式标志的枚举组件)。
互补:bevy-character-movement(集成路径点或速度)、bevy-spatial-queries(传感器与空间查询)。
下游/消费者:暂无。
主技能:bevy-master(Bevy 路由器)。