多窗口
Bevy 支持同时运行多个窗口。每个窗口是一个实体,带有 Window 组件。相机通过 RenderTarget::Window(WindowRef::Entity(...)) 指定渲染到哪个窗口。
rust
use bevy::prelude::*;
use bevy::window::WindowRef;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_systems(Startup, setup)
.run();
}
fn setup(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
// 主窗口相机
commands.spawn((
Camera3d::default(),
Transform::from_xyz(0.0, 0.0, 6.0).looking_at(Vec3::ZERO, Vec3::Y),
));
// 第二个窗口
let second_window = commands
.spawn(Window {
title: "第二个窗口".to_owned(),
..default()
})
.id();
// 第二个窗口的相机——朝另一个方向看
commands.spawn((
Camera3d::default(),
Transform::from_xyz(6.0, 0.0, 0.0).looking_at(Vec3::ZERO, Vec3::Y),
bevy::camera::RenderTarget::Window(WindowRef::Entity(second_window)),
));
// 共享场景内容
commands.spawn((
Mesh3d(meshes.add(Cuboid::new(1.0, 1.0, 1.0))),
MeshMaterial3d(materials.add(Color::srgb(0.2, 0.7, 0.9))),
));
commands.spawn((
DirectionalLight::default(),
Transform::from_xyz(3.0, 3.0, 3.0).looking_at(Vec3::ZERO, Vec3::Y),
));
info!("双窗口已创建——从不同角度观察同一个场景");
}Listing 35-2:双窗口——从不同角度观察同一场景
工作原理
DefaultPlugins创建主窗口实体(带PrimaryWindow标记组件)- 用
commands.spawn(Window { ... })创建额外窗口实体 - 相机的
RenderTarget指向目标窗口实体 - 每个相机独立渲染,可以有不同的位置、投影、甚至不同的场景内容
窗口引用
WindowRef 有两种:
WindowRef::Entity(Entity):通过实体引用WindowRef::Primary:引用主窗口
主窗口的相机不需要显式设置 RenderTarget——默认就是主窗口。
注意事项
- 每个窗口都需要一个相机。如果没有相机指向某个窗口,该窗口就是黑屏。
- 窗口的 DPI 缩放由操作系统控制。
WindowResolution是逻辑尺寸,物理像素 = 逻辑尺寸 × scale_factor。 - 第二个窗口的关闭不会触发 App 退出,除非
exit_condition设置为OnAllClosed。 - 窗口实体可以被
despawn,窗口会随之关闭。