远程调试:bevy_remote 与 BRP
bevy_remote 提供了 BRP(Bevy Remote Protocol)——一个基于 JSON-RPC 的远程接口,允许外部工具在运行时检查和修改 Bevy 世界。
启用 BRP
BRP 不在 Bevy 的默认 feature 中,需要在 Cargo.toml 中启用:
toml
bevy = { version = "=0.18.1", features = ["bevy_remote"] }然后在 App 中注册两个插件:
rust
use bevy::prelude::*;
use bevy::remote::{http::RemoteHttpPlugin, RemotePlugin};
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugins(RemotePlugin::default())
.add_plugins(RemoteHttpPlugin::default())
.add_systems(Startup, setup)
.run();
}
fn setup() {
info!("BRP 服务已启动——监听 127.0.0.1:15702");
info!("用 curl 或 BRP 客户端连接即可检查和修改世界");
}Listing 33-5:启用 BRP——RemotePlugin + RemoteHttpPlugin
RemotePlugin::default() 注册了所有内置方法,RemoteHttpPlugin::default() 启动 HTTP 服务器,默认监听 127.0.0.1:15702。
内置 BRP 方法
BRP 提供了以下内置方法:
| 方法名 | 功能 |
|---|---|
world.get_components | 获取指定实体上的组件 |
world.query | 按组件类型查询实体 |
world.spawn_entity | 远程生成实体 |
world.insert_components | 向实体插入组件 |
world.remove_components | 从实体移除组件 |
world.despawn_entity | 销毁实体 |
world.reparent_entities | 修改实体的父子关系 |
world.list_components | 列出实体上的所有组件 |
world.mutate_components | 修改组件字段 |
world.get_components+watch | 获取组件并持续监听变更 |
world.get_resources | 获取资源 |
world.insert_resources | 插入/修改资源 |
world.remove_resources | 移除资源 |
world.trigger_event | 触发事件 |
registry.schema | 获取类型注册表的 schema |
用 curl 测试
启动 App 后,可以用 curl 发送 JSON-RPC 请求:
bash
# 查询所有带 Transform 组件的实体
curl -X POST http://127.0.0.1:15702/ \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"world.query","params":{"component":"bevy_transform::components::transform::Transform"}}'
# 获取指定实体的所有组件
curl -X POST http://127.0.0.1:15702/ \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":2,"method":"world.get_components","params":{"entity":1}}'自定义 BRP 方法
RemotePlugin 支持 with_method 注册自定义方法。方法签名是 impl IntoSystem<In<Option<Value>>, BrpResult, M>,接收 JSON 值,返回 JSON 结果:
rust
RemotePlugin::default()
.with_method("my_custom_method", my_handler_system)可序列化组件
为了让 BRP 能读写你的自定义组件,组件需要实现 Reflect、Serialize、Deserialize,并在 #[reflect(...)] 中注册:
rust
use bevy::prelude::*;
use bevy::remote::{http::RemoteHttpPlugin, RemotePlugin};
use serde::{Deserialize, Serialize};
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugins(RemotePlugin::default())
.add_plugins(RemoteHttpPlugin::default())
.add_systems(Startup, setup)
.add_systems(Update, bounce)
.run();
}
#[derive(Component, Reflect, Serialize, Deserialize)]
#[reflect(Component, Serialize, Deserialize)]
struct Bouncer {
speed: f32,
amplitude: f32,
}
fn setup(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
commands.spawn((
Mesh3d(meshes.add(Cuboid::new(1.0, 1.0, 1.0))),
MeshMaterial3d(materials.add(Color::srgb(0.2, 0.7, 0.9))),
Transform::from_xyz(0.0, 0.5, 0.0),
Bouncer {
speed: 2.0,
amplitude: 1.5,
},
));
commands.spawn((
Mesh3d(meshes.add(Plane3d::default().mesh().size(8.0, 8.0))),
MeshMaterial3d(materials.add(Color::srgb(0.3, 0.3, 0.3))),
));
commands.spawn((
PointLight {
contact_shadows_enabled: true,
..default()
},
Transform::from_xyz(4.0, 8.0, 4.0),
));
commands.spawn((
Camera3d::default(),
Transform::from_xyz(-2.5, 4.5, 9.0).looking_at(Vec3::ZERO, Vec3::Y),
));
info!("BRP 检查器示例启动——用 curl 查看/修改 Bouncer 组件");
}
fn bounce(mut query: Query<(&mut Transform, &Bouncer)>, time: Res<Time>) {
for (mut transform, bouncer) in &mut query {
transform.translation.y =
0.5 + bouncer.amplitude * (time.elapsed_secs() * bouncer.speed).cos();
}
}Listing 33-6:BRP 检查器——可被远程读写的 Bouncer 组件
#[reflect(Component, Serialize, Deserialize)] 告诉 Bevy 的反射系统,这个组件可以被 BRP 序列化和反序列化。