Skip to content

远程调试: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 能读写你的自定义组件,组件需要实现 ReflectSerializeDeserialize,并在 #[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 序列化和反序列化。