Skip to content

多窗口

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:双窗口——从不同角度观察同一场景

工作原理

  1. DefaultPlugins 创建主窗口实体(带 PrimaryWindow 标记组件)
  2. commands.spawn(Window { ... }) 创建额外窗口实体
  3. 相机的 RenderTarget 指向目标窗口实体
  4. 每个相机独立渲染,可以有不同的位置、投影、甚至不同的场景内容

窗口引用

WindowRef 有两种:

  • WindowRef::Entity(Entity):通过实体引用
  • WindowRef::Primary:引用主窗口

主窗口的相机不需要显式设置 RenderTarget——默认就是主窗口。

注意事项

  • 每个窗口都需要一个相机。如果没有相机指向某个窗口,该窗口就是黑屏。
  • 窗口的 DPI 缩放由操作系统控制。WindowResolution 是逻辑尺寸,物理像素 = 逻辑尺寸 × scale_factor。
  • 第二个窗口的关闭不会触发 App 退出,除非 exit_condition 设置为 OnAllClosed
  • 窗口实体可以被 despawn,窗口会随之关闭。