Writing Brief: Bevy 里「overlay」到底怎么实现的
版本锚点:正文以
v0.19.0(git show v0.19.0:crates/bevy_dev_tools/...)为准;main上diagnostics_overlay.rs行数与 0.19.0 一致,后续小修见 #24433、#24611。
不是 Bevy 统一 API:文中用「四类叠层」避免读者以为有一个Overlaytrait。
目标
| 项 | 建议 |
|---|---|
| 公众号标题 | ≤12 字,例:「Bevy 调试叠层」 / 「四层叠层怎么叠」 |
| 副标题(frontmatter title) | Bevy 调试叠层:Diagnostic、FPS、渲染与 UI 线框 |
| 受众 | 已写过 Bevy App/Plugin,想少造轮子、搞清 dev_tools 边界的中文开发者 |
| 风格 | 杂志技术稿:先地图后细节;代码块短、可 cargo run --example fps_overlay 验证 |
| 长度 | 2800–3500 字(单篇专题,不塞进 0.19 总览) |
| 正文落点 | Vault My Blog/(share: false 起草) |
一句话论点
Bevy 的 overlay 是 四条并行管线(UI 诊断窗、UI FPS HUD、3D 缓冲区全屏 shader、UI 布局线框),共同点是「叠在画面上」,实现上 只有前两类在 bevy_dev_tools,后两类分别在 render_debug 与 bevy_ui_render extract 阶段。
建议结构(按节写)
1. 开场:为什么 0.19 值得单独讲 overlay(~300 字)
- 以前:
FrameTimeDiagnosticsPlugin+ 自己 spawnText+GlobalZIndex。 - 0.19:#22486
DiagnosticsOverlayPlugin— spawn 带DiagnosticsOverlayComponent 即得可拖、可折叠窗口。 - 澄清:
RenderDebugOverlay很多 3D 项目 已在DefaultPlugins里(bevy_dev_tools+bevy_pbr),和 Diagnostic 窗 不是同一套。
2. 总览图(必配 ASCII 或 Mermaid)
flowchart LR subgraph ui_dev["bevy_ui 叠层"] D[DiagnosticsOverlayPlugin] F[FpsOverlayPlugin] end subgraph diag["bevy_diagnostic"] S[DiagnosticsStore] end subgraph render["RenderApp"] R[RenderDebugOverlayPlugin] end subgraph ui_dbg["bevy_ui_render extract"] U[extract_debug_overlay] end S --> D S --> F R --> ViewTarget U --> ExtractedUiNodes
3. DiagnosticsOverlay — 数据到窗口(~900 字)★核心
源码:crates/bevy_dev_tools/src/diagnostics_overlay.rs
| 概念 | 作用 |
|---|---|
DiagnosticsOverlay | Component:title + items: Vec<DiagnosticsOverlayItem> |
DiagnosticsOverlayItem | path + statistic(Value/Average/Smoothed)+ precision |
DiagnosticsOverlayPlane | PreStartup 全屏根,GlobalZIndex(1_000_000) |
DiagnosticsOverlayPlugin | Observers + 每秒 rebuild_diagnostics_list |
生命周期(写作时按顺序讲):
PreStartup::build_plane— 一个 Plane,子 overlay 都挂下面。commands.spawn(DiagnosticsOverlay::fps())—On<Add, DiagnosticsOverlay>→build_overlay建标题栏 + Grid 内容区。- 每秒从
DiagnosticsStore读数;未注册路径显示Missing(教读者补对应 diagnostic plugin)。 - 交互:拖标题改
Node top/left;点标题折叠 Grid;点窗口ChildOf重挂 Plane 置顶。 Pickable::should_block_lower: false— 不抢游戏点击。
可贴代码(0.19 合法):
use bevy::prelude::*;
use bevy::dev_tools::diagnostics_overlay::{
DiagnosticsOverlay, DiagnosticsOverlayItem, DiagnosticsOverlayPlugin,
DiagnosticsOverlayStatistic,
};
use bevy::diagnostic::FrameTimeDiagnosticsPlugin;
fn main() {
App::new()
.add_plugins((DefaultPlugins, FrameTimeDiagnosticsPlugin::default()))
.add_plugins(DiagnosticsOverlayPlugin)
.add_systems(Startup, |mut c: Commands| {
c.spawn(DiagnosticsOverlay::fps());
c.spawn(DiagnosticsOverlay::mesh_and_standard_material());
})
.run();
}注意:
mesh_and_standard_material()方法名(单数 material);release note 里偶写mesh_and_standard_materials()以源码为准。
预设与依赖:
fps()→ 需FrameTimeDiagnosticsPlugin(FPS overlay 插件会自动加,Diagnostic 窗 不会 自动加 frame plugin,文中写清读者要自己add_plugins)。mesh_and_standard_material()→ 需MeshAllocatorDiagnosticPlugin、MaterialAllocatorDiagnosticPlugin<StandardMaterial>等已注册路径。
4. FpsOverlay — 何时不用 Diagnostic 窗(~500 字)
源码:fps_overlay.rs + frame_time_graph/
- 一个
FpsOverlayConfigResource,Startup 建固定 UI 树。 GlobalZIndex(i32::MAX - 32);update_text用on_timer(refresh_interval)默认 100ms。- 可选 帧时间柱状图:
UiMaterialPlugin<FrametimeGraphMaterial>+ShaderBuffer;WebGL 无 webgpu 时 warn 并跳过。 - 文内引用官方态度:优先平台原生 HUD(Metal
MTL_HUD_ENABLED=1),应用内 overlay 有刷新开销。
示例命令:cargo run --example fps_overlay --features bevy_dev_tools(按项目 feature 表写一句怎么开 dev_tools)。
5. RenderDebugOverlay — 叠在 3D 画面上(~500 字)
源码:render_debug.rs,shader debug_overlay.wgsl
- 插入点:
Core3d中PostProcess之后、ui_pass之前(文章画一条简化渲染顺序条)。 - F1 循环
RenderDebugMode(depth / normal / motion / deferred…),按相机 prepass 能力跳过。 - 与 Diagnostic 正交:读 GPU buffer,不读
DiagnosticsStore。 - 默认插件组:
default_plugins.rs里bevy_dev_tools+bevy_pbr时自动加入。
6. UI Debug — 不是窗口,是假节点(~400 字)
源码:bevy_ui_render/src/debug_overlay.rs,feature bevy_ui_debug(bevy_ui_render default 常开)
GlobalUiDebugOptions/ 每节点UiDebugOptions。extract_debug_overlay向ExtractedUiNodes追加 border 类型节点,颜色Hsla::sequential_dispersed(entity)。- 0.19 迁移:与
GlobalUiDebugOverlay/ component 拆分(可一句带过 migration guide,不深挖 Resources-as-Components)。
7. 选型表(收尾实用)
| 我要… | 用 |
|---|---|
| 多指标、可拖、可关内容区 | DiagnosticsOverlayPlugin |
| 角落 FPS + 柱状图 | FpsOverlayPlugin |
| 看 depth/normal/deferred | RenderDebugOverlay(F1/F2) |
| 调 padding/content 盒 | GlobalUiDebugOptions |
8. 常见坑(Pitfalls 小节)
- 显示
Missing→ diagnostic plugin / path 未注册。 - Diagnostic 窗 1s 刷新 vs FPS HUD 100ms — 别用来盯单帧尖峰。
- 不要把四类叠层混成「开一个 Plugin 全搞定」。
- 写教程时 Diagnostics 与 FpsOverlay 都要显式
add_plugins;RenderDebug 可能已在 Default 里。 - 自定义 diagnostic:先
register路径,再DiagnosticsOverlay::new("标题", vec![path.into()])。
素材与验证命令
cd ~/workspace/bevy
git show v0.19.0:crates/bevy_dev_tools/src/diagnostics_overlay.rs | head -80
cargo run --release --example fps_overlay # 确认本地 features
rg 'DiagnosticsOverlayPlugin' crates/bevy_internal examples/配图建议
DiagnosticsOverlay双窗口(fps + mesh/material)截图 — 自写最小 demo 或等 scene_viewer 合入后截官方 example。fps_overlayexample 绿字 + 柱状图。- RenderDebug F1 切 depth 一帧(注明需 prepass)。
- UI debug 多色线框(
full_ui+ feature)。
与现有 wiki / 博客关系
- 不重复
bevy-0-19-release-brief.md全文;可在 0.19 总览文末链到本篇「调试叠层专题」。 - 可链 bevy、concepts 里 diagnostic 相关页(若有)。
- PR 时间线:
aeb9e0e16#22486;21e8ab211PreStartup;73d4aa3c7fixes。
Writer 完成定义
- 四类叠层各有一句「数据从哪来、画在哪」
- 至少一个可运行 minimal
DiagnosticsOverlay示例 - 标明 v0.19.0,不混 main 未发布 API
- 无「单一 Overlay 系统」表述
- 代码在
cargo check或 example 级别可验证(writer/coder profile 可代跑)