Customizable Performance/Debug Overlay for Bevy UI

Overview

Customizable Performance/Debug Overlay for Bevy UI

Crates.io docs MIT/Apache 2.0

Sponsor me:

GitHub Sponsors

Bevy Compatibility:

Bevy Version Plugin Version
0.14 0.3
0.13 0.2,0.1

This crate provides an implementation of an in-game performance/debug UI overlay for the Bevy game engine.

The goal of this crate is to make it as useful as possible for any Bevy project:

  • Made with Bevy UI (not egui or any other 3rd-party UI solution)
  • Easy to set up (see simple example)
  • Modular! You decide what info you want to display!
    • Choose any combination of predefined entries (see specific_entries example):
      • Framerate (FPS), Frame Time, Frame Count, ECS Entity Count, CPU Usage, RAM Usage, Wall Clock, Running Time, Fixed Time Step, Fixed Overstep, Cursor Position, Window Resolution, Window Scale Factor, Window Mode, Present Mode
    • Implement your own custom entries to display anything you like!
  • Customizable appearance/styling (see settings, fps_minimalist examples)
  • Support for highlighting values using a custom font or color!
    • Allows you to quickly notice if something demands your attention.

Spawning a Perf UI can be as simple as:

commands.spawn(PerfUiBundle::default());

This creates a Perf UI with a curated selection of entries, which are in my opinion the most useful out of everything provided in this crate.

If you want a UI with all the available entries (not recommended due to performance overhead):

commands.spawn(PerfUiCompleteBundle::default());

If you want to create a Perf UI with specific entries of your choice, just spawn an entity with PerfUiRoot + your desired entries, instead of using the above bundles.

commands.spawn((
   PerfUiRoot::default(),
   PerfUiEntryFPS::default(),
   PerfUiEntryClock::default(),
   // ...
));

There are also some bundles to help you add some common groups of entries:

commands.spawn((
   PerfUiRoot::default(),
   // Contains everything related to FPS and frame time
   PerfUiFramerateEntries::default(),
   // Contains everything related to the window and cursor
   PerfUiWindowEntries::default(),
   // Contains everything related to system diagnostics (CPU, RAM)
   PerfUiSystemEntries::default(),
   // Contains everything related to fixed timestep
   PerfUiFixedTimeEntries::default(),
   // ...
));

If you want to customize the appearance, set the various fields in each of the structs, instead of using default().

Screenshot of the simple example showing default configuration

Screenshot of the settings example showing multiple UIs with custom configuration

Fancy Widgets

It is possible to visualize the value in other ways, not just display it as text.

iyes_perf_ui currently provides one such widget implementation: Bar. To use it, wrap your entries in PerfUiWidgetBar.

For example, to display FPS as a Bar:

commands.spawn((
   PerfUiRoot::default(),
   PerfUiWidgetBar::new(PerfUiEntryFPS::default()),
   // ...
));

If you want to create your own custom widgets, have a look at implementing the PerfUiWidget trait.

Performance Warning!

This crate is somewhere in-between "a useful diagnostic/dev tool" and "a tech demo".

Unfortunately, it does introduce significant overhead to your app, especially if you spawn a "complete" UI with lots of entries/widgets.

Please keep this in mind: your game will run faster when you don't have a Perf UI spawned. Silver lining: If your performance seems good with the Perf UI, it will be even better without. ;)

To make it more representative of your actual performance, consider spawning a more minimal Perf UI with just a few entries that are most useful to you (for example: fps, frame time), instead of a "complete" UI.


I know it is ironic that a tool intended to help you measure your performance ends up significantly degrading your performance. I am thinking about ways to reduce the overhead.

From my own measurements, most of the overhead comes from bevy_ui's layout system struggling to update the complex layout of the Perf UI, not from any of the actual code in iyes_perf_ui. So, to improve perfomance, I will need to come up with a way to simplify the UI and make it easier for Bevy to process. Or Bevy will have to get better at UI layout. ;)

Comments
  • [Feature Request] Hiding and Unhiding

    [Feature Request] Hiding and Unhiding

    Hi,

    First thanks for making this package, it is super useful.

    I may be wrong, I'm new to Bevy, but there seems to be no easy way to hide and unhide the UI. I feel like this would be a useful feature as it will allow us to incorporate these into in-game settings.

    opened by EuanHoll 6
  • Can't spawn after Startup

    Can't spawn after Startup

    Maybe I just misunderstand something basic about Bevy UI. :)

    I wanted a key to toggle the UI, but I get this error:

    2024-04-03T02:39:37.117705Z  WARN bevy_ui::layout: Unstyled child in a UI entity hierarchy. You are using an entity without UI components as a child of an entity with UI components, results may be unexpected.
    thread 'Compute Task Pool (22)' panicked at /home/emblemparade/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_ui-0.13.1/src/layout/mod.rs:132:60:
    called `Option::unwrap()` on a `None` value
    

    My code:

    impl Plugin for MyPlugin {
        fn build(&self, app: &mut App) {
            app.init_state::<Mode>()
                .add_plugins((
                    FrameTimeDiagnosticsPlugin,
                    EntityCountDiagnosticsPlugin,
                    SystemInformationDiagnosticsPlugin,
                    PerfUiPlugin,
                ))
                .add_systems(Update, handle_input);
        }
    }
    
    fn handle_input(
        mut commands: Commands,
        input: Res<ButtonInput<KeyCode>>,
        perfs: Query<Entity, With<PerfUiRoot>>,
    ) {
        if input.just_pressed(KeyCode::F1) {
            match perfs.get_single() {
                Ok(perf) => {
                    println!("remove perf!");
                    commands.entity(perf).despawn_recursive();
                }
                Err(_) => {
                    println!("perf!");
                    commands.spawn(PerfUiCompleteBundle::default());
                }
            }
        }
    }
    
    opened by tliron 2
  • Add support for a different inner background color for highlighted entries.

    Add support for a different inner background color for highlighted entries.

    Currently highlighting only changes the font. It is thus only useful if the user has custom fonts.

    We could make it so highlighted entries also get a different background color. This would also help bring even more visual attention to them.

    enhancement 
    opened by inodentry 0
  • Allow disabling labels

    Allow disabling labels

    Make it possible to create a Perf UI that only displays values, without labels. This should be a setting on the PerfUiRoot which controls whether UI nodes are spawned for the labels column.

    Supporting this would allow users to just make a minimalist FPS counter (or any other metric they want to display, using our API) without any extra text.

    enhancement 
    opened by inodentry 0
  • Customizable labels for library-provided entries.

    Customizable labels for library-provided entries.

    In custom user entries, they can do whatever they want for the label string.

    But the entry types provided by us hardcode their label string.

    Make it configurable.

    enhancement 
    opened by inodentry 0
  • Support custom color gradients instead of hardcoding Red-Yellow-Green

    Support custom color gradients instead of hardcoding Red-Yellow-Green

    The color of values that use the gradient color helper are the only part of the appearance that is not currently customizable.

    It should be possible to configure custom colors and then have the crate lerp between them.

    This ofc opens the can of worms re: color lerping and color spaces 😆 😅 😭

    enhancement 
    opened by inodentry 0
  • Ability to remove entries after the UI has been spawned.

    Ability to remove entries after the UI has been spawned.

    Right now, if you try to remove an entry (by removing its component from the root entity), things break. This should be supported / handled properly.

    Adding new entries at runtime works just fine.

    bug 
    opened by inodentry 0
  • Ability to change all settings on existing Perf UIs and Entries.

    Ability to change all settings on existing Perf UIs and Entries.

    Right now some settings do not take effect if changed after the UI is already spawned. The stuff that is used as part of UI setup to set the relevant values in Bevy UI components.

    • Background colors
    • Padding/margins/etc
    • Font size
    • others?

    Current workaround: despawn the UI (do a despawn_recursive on the entity with the PerfUiRoot) and recreate it.

    bug 
    opened by inodentry 0
  • Port to bevy 0.14

    Port to bevy 0.14

    I also accidentally formatted a bunch of stuff due to having format on save in my editor. I can either revert the formatting changes or run cargo fmt in a separate commit depending on what you prefer.

    I tested the examples and they all seem to work.

    opened by kristoff3r 0
  • doc: Add a FAQ section

    doc: Add a FAQ section

    Hello,

    Thanks for creating this plugin. It is cool! This PR adds a FAQ section to the README.md file.

    It explains why Total CPU and Total RAM can be shown as N/A.

    opened by uggla 0
  • Include `PerfUiPlugin` in the README

    Include `PerfUiPlugin` in the README

    It took me a few minutes before I realized that I had to add PerfUiPlugin seems obvious that there would be a plugin in retrospect but I'm sure more people will make the same mistake I made. Consider adding it to the README :)

    opened by honungsburk 0
  • time: some sort of general API for displaying the value of a timer?

    time: some sort of general API for displaying the value of a timer?

    It could be useful if there was an easy built-in way to add entries for custom user components or resources containing timers, which could extract the timer value and display it.

    enhancement 
    opened by inodentry 0
  • Ability to control Timezone (or UTC) for clock (when `chrono` is enabled).

    Ability to control Timezone (or UTC) for clock (when `chrono` is enabled).

    Right now all Clock entries are either hardcoded to UTC if the chrono optional dep is disabled or to Localtime if the chrono optional dep is disabled.

    Without chrono, we can only display UTC. With chrono, it would be nice to give the user choice over what to display.

    enhancement 
    opened by inodentry 1
Owner
Indie Game Development with Bevy, by @inodentry
null
Engine / framework for creating highly customizable and user modable action RPG's

Rust RPG Toolkit PLEASE NOTE: this in early and very heavy development. API is subject to constant change, as it has newly transitioned from being a g

Ole A. Sjo Fasting 58 Dec 5, 2022
An attempt to create an easily customizable MMORPG game engine. Sky not included.

skyless Proof of concept of an easily customizable MMORPG game engine. Getting started Copy environment variables cp .env.example .env Start the engi

null 8 Nov 23, 2022
Using bevy and custom render pipelines in order to render many objects in a forest using chunks for performance.

bevy_efficient_forest_example Using bevy and custom render pipelines in order to render many objects in a forest using chunks for performance. Grass i

Henrik Djurestål 43 Jan 5, 2023
Minecraft-esque voxel engine prototype made with the bevy game engine. Pending bevy 0.6 release to undergo a full rewrite.

vx_bevy A voxel engine prototype made using the Bevy game engine. Goals and features Very basic worldgen Animated chunk loading (ala cube world) Optim

Lucas Arriesse 125 Dec 31, 2022
bevy-hikari is an implementation of voxel cone tracing global illumination with anisotropic mip-mapping in Bevy

Bevy Voxel Cone Tracing bevy-hikari is an implementation of voxel cone tracing global illumination with anisotropic mip-mapping in Bevy. Bevy Version

研究社交 208 Dec 27, 2022
A simple extension for `bevy-editor-pls` to support tilemap editing right inside the bevy app.

What is this This is a simple tilemap editor plugin, that hooks right into bevy_editor_pls to work with bevy_ecs_tilemap. It works completely within i

null 3 May 8, 2023
Bevy Simple Portals is a Bevy game engine plugin aimed to create portals.

Portals for Bevy Bevy Simple Portals is a Bevy game engine plugin aimed to create portals. Those portals are (for now) purely visual and can be used t

Sélène Amanita 11 May 28, 2023
Minecraft using Bevy and Bevy-Meshem

minecraft_bevy Minecraft_bevy was built to showcase bevy_meshem. After a week of developing it has: Chunk loading / unloading each chunk's mesh is bei

Adam 7 Oct 4, 2023
High performance Rust ECS library

Legion aims to be a feature rich high performance Entity component system (ECS) library for Rust game projects with minimal boilerplate. Getting Start

Amethyst Engine 1.4k Jan 5, 2023
A high-performance renderer to render glTF models that use the `KHR_materials_transmission` and `KHR_materials_volume` extensions.

This is a high-performance renderer designed among other things to render glTF models that use the KHR_materials_transmission and KHR_materials_volume

Ashley 21 Dec 5, 2022
Comparing performance of Rust math libraries for common 3D game and graphics tasks

mathbench mathbench is a suite of unit tests and benchmarks comparing the output and performance of a number of different Rust linear algebra librarie

Cameron Hart 137 Dec 8, 2022
A Bevy plugin for loading the LDtk 2D tile map format.

bevy_ldtk ( Tileset from "Cavernas" by Adam Saltsman ) A Bevy plugin for loading LDtk tile maps. Usage use bevy::prelude::*; use bevy_ldtk::*; fn mai

Katharos Technology 23 Jul 4, 2022
Basic first-person fly camera for the Bevy game engine

bevy_flycam A basic first-person fly camera for Bevy 0.4 Controls WASD to move horizontally SPACE to ascend LSHIFT to descend ESC to grab/release curs

Spencer Burris 85 Dec 23, 2022
An ergonomic physics API for bevy games.

Heron An ergonomic physics API for 2d and 3d bevy games. (powered by rapier) How it looks like fn main() { App::build() .add_plugins(DefaultPlug

Jonathan Cornaz 313 Dec 16, 2022
Inspector plugin for the bevy game engine

bevy-inspector-egui This crate provides the ability to annotate structs with a #[derive(Inspectable)], which opens a debug interface using egui where

Jakob Hellermann 517 Dec 31, 2022
A plugin for Egui integration into Bevy

bevy_egui This crate provides a Egui integration for the Bevy game engine. Features: Desktop and web (bevy_webgl2) platforms support Clipboard (web su

Vladyslav Batyrenko 453 Jan 3, 2023
Crossterm plugin for the bevy game engine

What is bevy_crossterm? bevy_crossterm is a Bevy plugin that uses crossterm as a renderer. It provides custom components and events which allow users

null 79 Nov 2, 2022
A 4X style camera for bevy.

A 4X style camera for bevy. Demo Default Key Bindings: W / A / S / D / Arrow Keys / Mouse Left - Move along the horizontal plane Q / E / Mouse Right -

null 30 Jan 4, 2023
Game physics in one weekend with bevy

Game Physics in a Weekend (in Rust) This project is an implementation of the Game Physics in a Weekend book using the Rust programming language and th

Cameron Hart 28 Dec 23, 2022