Struct bevy::diagnostic::Diagnostic
pub struct Diagnostic {
pub suffix: Cow<'static, str>,
pub is_enabled: bool,
/* private fields */
}
Expand description
A timeline of DiagnosticMeasurement
s of a specific type.
Diagnostic examples: frames per second, CPU usage, network latency
Fields§
§suffix: Cow<'static, str>
§is_enabled: bool
Implementations§
§impl Diagnostic
impl Diagnostic
pub fn add_measurement(&mut self, measurement: DiagnosticMeasurement)
pub fn add_measurement(&mut self, measurement: DiagnosticMeasurement)
Add a new value as a DiagnosticMeasurement
.
pub fn new(path: DiagnosticPath) -> Diagnostic
pub fn new(path: DiagnosticPath) -> Diagnostic
Create a new diagnostic with the given path.
Examples found in repository?
10 11 12 13 14 15 16 17 18 19 20 21 22
fn main() {
App::new()
.add_plugins((
DefaultPlugins,
// The "print diagnostics" plugin is optional.
// It just visualizes our diagnostics in the console.
LogDiagnosticsPlugin::default(),
))
// Diagnostics must be initialized before measurements can be added.
.register_diagnostic(Diagnostic::new(SYSTEM_ITERATION_COUNT).with_suffix(" iterations"))
.add_systems(Update, my_system)
.run();
}
pub fn with_max_history_length(self, max_history_length: usize) -> Diagnostic
pub fn with_max_history_length(self, max_history_length: usize) -> Diagnostic
Set the maximum history length.
pub fn with_suffix(self, suffix: impl Into<Cow<'static, str>>) -> Diagnostic
pub fn with_suffix(self, suffix: impl Into<Cow<'static, str>>) -> Diagnostic
Add a suffix to use when logging the value, can be used to show a unit.
Examples found in repository?
10 11 12 13 14 15 16 17 18 19 20 21 22
fn main() {
App::new()
.add_plugins((
DefaultPlugins,
// The "print diagnostics" plugin is optional.
// It just visualizes our diagnostics in the console.
LogDiagnosticsPlugin::default(),
))
// Diagnostics must be initialized before measurements can be added.
.register_diagnostic(Diagnostic::new(SYSTEM_ITERATION_COUNT).with_suffix(" iterations"))
.add_systems(Update, my_system)
.run();
}
pub fn with_smoothing_factor(self, smoothing_factor: f64) -> Diagnostic
pub fn with_smoothing_factor(self, smoothing_factor: f64) -> Diagnostic
The smoothing factor used for the exponential smoothing used for
smoothed
.
If measurements come in less frequently than smoothing_factor
seconds
apart, no smoothing will be applied. As measurements come in more
frequently, the smoothing takes a greater effect such that it takes
approximately smoothing_factor
seconds for 83% of an instantaneous
change in measurement to e reflected in the smoothed value.
A smoothing factor of 0.0 will effectively disable smoothing.
pub fn path(&self) -> &DiagnosticPath
pub fn measurement(&self) -> Option<&DiagnosticMeasurement>
pub fn measurement(&self) -> Option<&DiagnosticMeasurement>
Get the latest measurement from this diagnostic.
pub fn value(&self) -> Option<f64>
pub fn value(&self) -> Option<f64>
Get the latest value from this diagnostic.
Examples found in repository?
520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542
fn counter_system(
diagnostics: Res<DiagnosticsStore>,
counter: Res<BevyCounter>,
mut query: Query<&mut Text, With<StatsText>>,
) {
let mut text = query.single_mut();
if counter.is_changed() {
text.sections[1].value = counter.count.to_string();
}
if let Some(fps) = diagnostics.get(&FrameTimeDiagnosticsPlugin::FPS) {
if let Some(raw) = fps.value() {
text.sections[3].value = format!("{raw:.2}");
}
if let Some(sma) = fps.average() {
text.sections[5].value = format!("{sma:.2}");
}
if let Some(ema) = fps.smoothed() {
text.sections[7].value = format!("{ema:.2}");
}
};
}
pub fn average(&self) -> Option<f64>
pub fn average(&self) -> Option<f64>
Return the simple moving average of this diagnostic’s recent values. N.B. this a cheap operation as the sum is cached.
Examples found in repository?
520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542
fn counter_system(
diagnostics: Res<DiagnosticsStore>,
counter: Res<BevyCounter>,
mut query: Query<&mut Text, With<StatsText>>,
) {
let mut text = query.single_mut();
if counter.is_changed() {
text.sections[1].value = counter.count.to_string();
}
if let Some(fps) = diagnostics.get(&FrameTimeDiagnosticsPlugin::FPS) {
if let Some(raw) = fps.value() {
text.sections[3].value = format!("{raw:.2}");
}
if let Some(sma) = fps.average() {
text.sections[5].value = format!("{sma:.2}");
}
if let Some(ema) = fps.smoothed() {
text.sections[7].value = format!("{ema:.2}");
}
};
}
pub fn smoothed(&self) -> Option<f64>
pub fn smoothed(&self) -> Option<f64>
Return the exponential moving average of this diagnostic.
This is by default tuned to behave reasonably well for a typical
measurement that changes every frame such as frametime. This can be
adjusted using with_smoothing_factor
.
Examples found in repository?
132 133 134 135 136 137 138 139 140 141 142 143 144
fn text_update_system(
diagnostics: Res<DiagnosticsStore>,
mut query: Query<&mut Text, With<FpsText>>,
) {
for mut text in &mut query {
if let Some(fps) = diagnostics.get(&FrameTimeDiagnosticsPlugin::FPS) {
if let Some(value) = fps.smoothed() {
// Update the value of the second section
text.sections[1].value = format!("{value:.2}");
}
}
}
}
More examples
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
fn ui_system(mut query: Query<&mut Text>, config: Res<Config>, diag: Res<DiagnosticsStore>) {
let mut text = query.single_mut();
let Some(fps) = diag
.get(&FrameTimeDiagnosticsPlugin::FPS)
.and_then(|fps| fps.smoothed())
else {
return;
};
text.sections[0].value = format!(
"Line count: {}\n\
FPS: {:.0}\n\n\
Controls:\n\
Up/Down: Raise or lower the line count.\n\
Spacebar: Toggle fancy mode.",
config.line_count, fps,
);
}
520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542
fn counter_system(
diagnostics: Res<DiagnosticsStore>,
counter: Res<BevyCounter>,
mut query: Query<&mut Text, With<StatsText>>,
) {
let mut text = query.single_mut();
if counter.is_changed() {
text.sections[1].value = counter.count.to_string();
}
if let Some(fps) = diagnostics.get(&FrameTimeDiagnosticsPlugin::FPS) {
if let Some(raw) = fps.value() {
text.sections[3].value = format!("{raw:.2}");
}
if let Some(sma) = fps.average() {
text.sections[5].value = format!("{sma:.2}");
}
if let Some(ema) = fps.smoothed() {
text.sections[7].value = format!("{ema:.2}");
}
};
}
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224
fn change_text_system(
time: Res<Time>,
diagnostics: Res<DiagnosticsStore>,
mut query: Query<&mut Text, With<TextChanges>>,
) {
for mut text in &mut query {
let mut fps = 0.0;
if let Some(fps_diagnostic) = diagnostics.get(&FrameTimeDiagnosticsPlugin::FPS) {
if let Some(fps_smoothed) = fps_diagnostic.smoothed() {
fps = fps_smoothed;
}
}
let mut frame_time = time.delta_seconds_f64();
if let Some(frame_time_diagnostic) =
diagnostics.get(&FrameTimeDiagnosticsPlugin::FRAME_TIME)
{
if let Some(frame_time_smoothed) = frame_time_diagnostic.smoothed() {
frame_time = frame_time_smoothed;
}
}
text.sections[0].value = format!(
"This text changes in the bottom right - {fps:.1} fps, {frame_time:.3} ms/frame",
);
text.sections[2].value = format!("{fps:.1}");
text.sections[4].value = format!("{frame_time:.3}");
}
}
pub fn history_len(&self) -> usize
pub fn history_len(&self) -> usize
Return the number of elements for this diagnostic.
pub fn duration(&self) -> Option<Duration>
pub fn duration(&self) -> Option<Duration>
Return the duration between the oldest and most recent values for this diagnostic.
pub fn get_max_history_length(&self) -> usize
pub fn get_max_history_length(&self) -> usize
Return the maximum number of elements for this diagnostic.
pub fn values(&self) -> impl Iterator<Item = &f64>
pub fn measurements(&self) -> impl Iterator<Item = &DiagnosticMeasurement>
pub fn clear_history(&mut self)
pub fn clear_history(&mut self)
Clear the history of this diagnostic.
Trait Implementations§
Auto Trait Implementations§
impl Freeze for Diagnostic
impl RefUnwindSafe for Diagnostic
impl Send for Diagnostic
impl Sync for Diagnostic
impl Unpin for Diagnostic
impl UnwindSafe for Diagnostic
Blanket Implementations§
§impl<T, U> AsBindGroupShaderType<U> for T
impl<T, U> AsBindGroupShaderType<U> for T
§fn as_bind_group_shader_type(&self, _images: &RenderAssets<GpuImage>) -> U
fn as_bind_group_shader_type(&self, _images: &RenderAssets<GpuImage>) -> U
T
ShaderType
for self
. When used in AsBindGroup
derives, it is safe to assume that all images in self
exist.source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait>
(where Trait: Downcast
) to Box<dyn Any>
. Box<dyn Any>
can
then be further downcast
into Box<ConcreteType>
where ConcreteType
implements Trait
.§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait>
(where Trait: Downcast
) to Rc<Any>
. Rc<Any>
can then be
further downcast
into Rc<ConcreteType>
where ConcreteType
implements Trait
.§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &Any
’s vtable from &Trait
’s.§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &mut Any
’s vtable from &mut Trait
’s.§impl<T> DowncastSync for T
impl<T> DowncastSync for T
§impl<S> FromSample<S> for S
impl<S> FromSample<S> for S
fn from_sample_(s: S) -> S
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
source§impl<T> IntoEither for T
impl<T> IntoEither for T
source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moresource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read more