Answer
No, Bevy’s Schedule does not automatically suppress change‑detection overhead or skip a system when no entities match its Changed<T> filter. The change‑detection system still runs each frame, setting internal flags, and any system that declares Changed<T> is still invoked; it simply iterates over zero entities when the flag is unset.
Likely Explanation
Bevy’s default CoreStage includes a built‑in ChangeDetection system that runs before user systems. It walks component access logs and marks entities whose components were mutably accessed. Later systems query with Changed<T> to react only to those marks. Because the schedule invokes every system regardless of the query result, the only way to avoid the per‑system call overhead is to prevent the system from being scheduled at all.
Steps to Reduce or Eliminate Overhead
- Disable change detection globally (if you do not need it at all): remove the
bevy::ecs::schedule::ChangeDetectionPlugin or manually exclude the ChangeDetectionSystem from your Schedule. This eliminates the flag‑setting pass entirely.
- Skip a specific system when no changes occurred: add a
run_if condition that checks a global change token. For example, define a singleton resource that is set by the ChangeDetection system when any component of interest changes, then gate your system on that resource.
- Minimal overhead alternative: keep the system but rely on the fact that a
Query<&T, Changed<T>> with zero matches does almost no work beyond the system call. If the call cost is still problematic, use the run_if approach above.
Verification
To confirm that a system with Changed<T> runs zero iterations when no changes occurred:
fn debug_system(q: Query<&MyComp, Changed<MyComp>>) {
if q.is_empty() {
info!(target: "bevy_change", "System ran but found no changed entities");
} else {
for _ in q.iter() { info!(target: "bevy_change", "Changed entity processed"); }
}
}
Run the application with BEVY_LOG=debug and observe the log output; you should see the “found no changed entities” message each frame when no mutation happened.
Missing Diagnostic Detail
Are you using the default CoreStage or a custom Stage for your systems? The answer affects where you must insert or remove the ChangeDetectionSystem or attach a run_if condition.