网络编程

概述

学习目标

  • 理解 Bevy 网络编程的基本概念
  • 了解 RemotePlugin 的使用
  • 掌握服务器端开发
  • 掌握客户端开发
  • 理解网络同步机制

前置知识要求

  • ECS 基础
  • 系统调度基础
  • HTTP 基础
  • JSON-RPC 基础

核心概念

什么是网络编程?

网络编程是在 Bevy 应用中实现网络通信的功能。Bevy 提供了 RemotePluginRemoteHttpPlugin,允许通过网络连接远程访问和控制 Bevy 应用。

为什么需要网络编程?

  1. 远程调试:通过网络远程调试 Bevy 应用
  2. 远程控制:通过网络远程控制 Bevy 应用
  3. 多人游戏:实现多人游戏功能
  4. 工具集成:与外部工具集成

网络编程的核心组件

Bevy 网络编程系统包含以下核心组件:

  • RemotePlugin:远程插件,提供基本的远程功能
  • RemoteHttpPlugin:HTTP 远程插件,提供 HTTP 接口
  • BRP:Bevy Remote Protocol,Bevy 远程协议
  • JSON-RPC:JSON-RPC 协议,用于通信

基础用法

服务器端开发

创建服务器端应用。

源代码文件bevy/examples/remote/server.rs

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
use bevy::{
prelude::*,
remote::{http::RemoteHttpPlugin, RemotePlugin},
};

fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugins(RemotePlugin::default())
.add_plugins(RemoteHttpPlugin::default())
.add_systems(Startup, setup)
.add_systems(Update, move_cube)
.run();
}

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_u8(124, 144, 255))),
Transform::from_xyz(0.0, 0.5, 0.0),
Cube(1.0),
));

// 创建资源(可以被远程访问和修改)
commands.insert_resource(TestResource {
foo: Vec2::new(1.0, -1.0),
bar: false,
});

// 创建光照和相机
commands.spawn((
PointLight {
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),
));
}

#[derive(Resource, Reflect, Serialize, Deserialize)]
#[reflect(Resource, Serialize, Deserialize)]
pub struct TestResource {
pub foo: Vec2,
pub bar: bool,
}

#[derive(Component, Reflect, Serialize, Deserialize)]
#[reflect(Component, Serialize, Deserialize)]
struct Cube(f32);

fn move_cube(mut query: Query<&mut Transform, With<Cube>>, time: Res<Time>) {
for mut transform in &mut query {
transform.translation.y = -time.elapsed_secs().cos() + 1.5;
}
}

关键要点

  • 使用 RemotePlugin 启用远程功能
  • 使用 RemoteHttpPlugin 启用 HTTP 接口
  • 使用 #[derive(Reflect, Serialize, Deserialize)] 使资源可远程访问
  • 使用 #[reflect(Resource)]#[reflect(Component)] 标记可远程访问的类型

说明
服务器端应用提供远程访问接口。通过 RemotePluginRemoteHttpPlugin,可以启用 HTTP 接口,允许客户端通过网络访问和控制应用。

客户端开发

创建客户端应用。

源代码文件bevy/examples/remote/client.rs

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
use bevy::{
prelude::*,
remote::{
builtin_methods::{
BrpQuery, BrpQueryFilter, BrpQueryParams, ComponentSelector, BRP_QUERY_METHOD,
},
http::{DEFAULT_ADDR, DEFAULT_PORT},
BrpRequest,
},
transform::components::Transform,
};

fn main() -> Result<(), anyhow::Error> {
let host_part = format!("{DEFAULT_ADDR}:{DEFAULT_PORT}");
let url = format!("http://{host_part}/");

// 查询所有 Transform 组件
run_transform_only_query(&url)?;

// 查询根实体
run_query_root_entities(&url)?;

// 查询所有组件和实体
run_query_all_components_and_entities(&url)?;

Ok(())
}

fn run_transform_only_query(url: &str) -> Result<(), anyhow::Error> {
let request = BrpRequest {
jsonrpc: String::from("2.0"),
method: String::from(BRP_QUERY_METHOD),
id: Some(serde_json::to_value(1)?),
params: Some(
serde_json::to_value(BrpQueryParams {
data: BrpQuery {
components: vec![std::any::type_name::<Transform>().to_string()],
..Default::default()
},
strict: false,
filter: BrpQueryFilter::default(),
})?,
),
};

let response = ureq::post(url)
.send_json(request)?
.body_mut()
.read_json::<serde_json::Value>()?;

println!("Transform query response: {response:#}");
Ok(())
}

关键要点

  • 使用 BrpRequest 创建 JSON-RPC 请求
  • 使用 BrpQuery 查询实体和组件
  • 使用 ComponentSelector 选择组件
  • 通过 HTTP POST 发送请求

说明
客户端应用通过网络访问服务器端应用。通过 JSON-RPC 协议,可以查询实体、组件、资源等,并可以修改它们。

网络同步机制

理解网络同步机制。

关键信息

  • 使用 Reflect trait 使类型可序列化
  • 使用 SerializeDeserialize 进行序列化
  • 通过 JSON-RPC 协议进行通信
  • 支持查询、修改、调用方法等操作

说明
网络同步机制允许客户端和服务器端同步数据。通过 ReflectSerializeDeserialize,可以将 Bevy 的类型序列化并通过网络传输。

进阶用法

自定义远程方法

实现自定义远程方法。

关键信息

  • 可以定义自定义的远程方法
  • 可以在服务器端实现自定义逻辑
  • 客户端可以调用这些方法

说明
自定义远程方法允许你实现自己的远程功能。这对于实现特定的网络功能非常有用。

网络优化

优化网络性能。

关键信息

  • 减少网络请求频率
  • 使用批量查询减少请求数量
  • 合理使用缓存
  • 优化序列化性能

说明
网络优化可以提高网络通信的性能。通过减少请求频率、使用批量查询、合理使用缓存等技术,可以显著提高性能。

实际应用

在游戏开发中的应用场景

网络编程在游戏开发中有广泛的应用:

  1. 远程调试:通过网络远程调试游戏
  2. 远程控制:通过网络远程控制游戏
  3. 多人游戏:实现多人游戏功能
  4. 工具集成:与外部工具集成

常见问题

问题 1:如何启用远程功能?

解决方案:添加 RemotePluginRemoteHttpPlugin 到应用中,使用 #[derive(Reflect)] 标记可远程访问的类型。

问题 2:如何查询远程实体?

解决方案:使用 BrpQuery 创建查询请求,通过 JSON-RPC 协议发送请求。

问题 3:如何修改远程资源?

解决方案:使用 BrpRequest 创建修改请求,通过 JSON-RPC 协议发送请求。

性能考虑

  1. 请求频率:减少网络请求频率
  2. 批量操作:使用批量查询和操作
  3. 缓存:合理使用缓存减少网络请求
  4. 序列化:优化序列化性能

相关资源

相关源代码文件

  • bevy/examples/remote/server.rs - 服务器端示例
  • bevy/examples/remote/client.rs - 客户端示例

官方文档链接

进一步学习建议

  • 学习 JSON-RPC 协议,了解通信机制
  • 学习 Reflect 系统,了解序列化机制
  • 学习网络编程,了解如何实现多人游戏

索引返回上级目录