Skip to content
21 changes: 21 additions & 0 deletions crates/bevy_ecs/src/schedule/condition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ mod sealed {
pub mod common_conditions {
use super::Condition;
use crate::{
prelude::{Added, Changed, Component, Query},
schedule::{State, States},
system::{In, IntoPipeSystem, ReadOnlySystem, Res, Resource},
};
Expand Down Expand Up @@ -141,4 +142,24 @@ pub mod common_conditions {
{
condition.pipe(|In(val): In<bool>| !val)
}

/// Generates a [`Condition`](super::Condition)-satisfying closure that returns `true`
/// if there are any entities with the added given component type.
///
/// It's recommended to use this condition only if there is only a few entities
/// with the component `T`. Otherwise this check could be expensive and hold
/// up the executor preventing it from running any systems during the check.
pub fn any_component_added<T: Component>() -> impl FnMut(Query<(), Added<T>>) -> bool {
move |query: Query<(), Added<T>>| !query.is_empty()
Copy link
Member

@james7132 james7132 Feb 16, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These potentially do a full world scan in the multithreaded executor, which not only runs single threaded but blocks any further system's run conditions from being evaluated and tasks launched. The only early return is if no archetypes match the query, everything else does a full scan, and will scale linearly with the number of those components in the world. This is relatively easy performance footgun, same with the other condition below.

Even with it documented, I still don't think it's a good idea to readily provide this to users without some form of archetype-level change detection optimization.

Copy link
Contributor Author

@Shatur Shatur Feb 16, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, this is what I mentioned in the description. I thought it's fine if documented. But your concern is exactly why it wasn't included in #7579.

}

/// Generates a [`Condition`](super::Condition)-satisfying closure that returns `true`
/// if there are any entities with the changed given component type.
///
/// It's recommended to use this condition only if there is only a few entities
/// with the component `T`. Otherwise this check could be expensive and hold
/// up the executor preventing it from running any systems during the check.
pub fn any_component_changed<T: Component>() -> impl FnMut(Query<(), Changed<T>>) -> bool {
move |query: Query<(), Changed<T>>| !query.is_empty()
}
}