Skip to content

FPS Overlay 与诊断

画完线之后,下一个开发期刚需是帧率。你的 Gizmos 画了三千条线,帧率从 60 掉到 22——你需要一个随时能看的数字。

Bevy 的 bevy_dev_tools crate 提供了 FpsOverlayPlugin:一个自动叠加在画面左上角的 FPS 计数器,可配置字体、颜色、刷新频率,还带一个可选的帧时间图。

启用 FPS Overlay

FpsOverlayPlugin 需要 bevy_dev_tools feature。在 Cargo.toml 里:

toml
bevy = { version = "=0.18.1", features = ["bevy_dev_tools"] }

然后在 App 里一行启用:

rust
FpsOverlayPlugin {
                config: FpsOverlayConfig {
                    text_config: TextFont {
                        font_size: FontSize::Px(36.0),
                        font_smoothing: FontSmoothing::default(),
                        ..default()
                    },
                    text_color: Color::srgb(0.0, 1.0, 0.0),
                    enabled: true,
                    ..default()
                },
            },

FpsOverlayConfig 的字段:

字段类型默认值说明
text_configTextFont32px字体大小、字模
text_colorColor白色文字颜色
enabledbooltrue是否显示
refresh_intervalDuration100ms刷新间隔
frame_time_graph_configFrameTimeGraphConfig60fps 目标帧时间图配置

FrameTimeGraphConfig 控制文字下方那条彩色小图——绿色表示帧时间在目标范围内,红色表示超出。min_fps 设最低可接受帧率(低于此值全红),target_fps 设目标帧率。

运行时修改

FpsOverlayConfig 是一个普通的 Resource,直接修改它就会触发 UI 更新:

rust
fn toggle_overlay(
    keyboard: Res<ButtonInput<KeyCode>>,
    mut config: ResMut<FpsOverlayConfig>,
) {
    if keyboard.just_pressed(KeyCode::KeyF) {
        config.enabled = !config.enabled;
    }
    if keyboard.just_pressed(KeyCode::KeyG) {
        config.frame_time_graph_config.enabled =
            !config.frame_time_graph_config.enabled;
    }
}

这个系统监听 F 键切换 FPS 显示、G 键切换帧时间图。resource_changed 条件让 UI 只在配置真正变化时才重建。

完整示例

rust
use bevy::dev_tools::fps_overlay::{FpsOverlayConfig, FpsOverlayPlugin};
use bevy::prelude::*;
use bevy::text::FontSmoothing;

fn main() {
    App::new()
        .add_plugins((
            DefaultPlugins,
            // ANCHOR: fps_plugin
            FpsOverlayPlugin {
                config: FpsOverlayConfig {
                    text_config: TextFont {
                        font_size: FontSize::Px(36.0),
                        font_smoothing: FontSmoothing::default(),
                        ..default()
                    },
                    text_color: Color::srgb(0.0, 1.0, 0.0),
                    enabled: true,
                    ..default()
                },
            },
            // ANCHOR_END: fps_plugin
        ))
        .add_systems(Startup, setup)
        .add_systems(Update, toggle_overlay)
        .run();
}

fn setup(mut commands: Commands) {
    commands.spawn(Camera2d);
    commands.spawn((
        Text::new("按 F 切换 FPS 显示\n按 G 切换帧时间图"),
        Node {
            position_type: PositionType::Absolute,
            bottom: px(12.0),
            left: px(12.0),
            ..default()
        },
    ));
}

// ANCHOR: toggle
fn toggle_overlay(
    keyboard: Res<ButtonInput<KeyCode>>,
    mut config: ResMut<FpsOverlayConfig>,
) {
    if keyboard.just_pressed(KeyCode::KeyF) {
        config.enabled = !config.enabled;
    }
    if keyboard.just_pressed(KeyCode::KeyG) {
        config.frame_time_graph_config.enabled =
            !config.frame_time_graph_config.enabled;
    }
}
// ANCHOR_END: toggle

Listing 27-4:FPS Overlay——帧率显示与帧时间图

运行:

console
cargo run -p ch27-devtools --example listing-27-04

左上角会出现绿色的 FPS 数字和一条帧时间图。按 F 切换数字显示,按 G 切换图表。

FpsOverlayPlugin 自动安装的依赖

FpsOverlayPlugin 内部会自动添加 FrameTimeDiagnosticsPlugin(如果你还没有手动加的话)。这个插件负责采集帧时间、FPS 等诊断数据,存入 DiagnosticsStore 资源。你可以用它做自定义的性能监控:

rust
fn read_fps(diagnostics: Res<DiagnosticsStore>) {
    if let Some(fps) = diagnostics.get(&FrameTimeDiagnosticsPlugin::FPS) {
        if let Some(value) = fps.smoothed() {
            // value 就是平滑后的 FPS
        }
    }
}

DiagnosticsStore 里不只有 FPS——帧时间、实体数量、内存使用等都是诊断项,每一项是一个带时间窗口的滑动平均值。你可以在运行时读取它们做自动降级、性能报警等。