Expand description
Checks for systems added to the FixedUpdate schedule that mutably query entities with a
Camera component.
§Motivation
Modifying the camera in FixedUpdate can cause jittery, inconsistent, or laggy visuals because
FixedUpdate may not run every render frame, especially on games with a high FPS.
§Known Issues
This lint only detects systems that explicitly use the With<Camera> query filter.
§Example
fn move_camera(mut query: Query<&mut Transform, With<Camera>>) {
// ...
}
fn main() {
App::new()
// Uh oh! This could cause issues because the camera may not move every frame!
.add_systems(FixedUpdate, move_camera);
}Use instead:
fn move_camera(mut query: Query<&mut Transform, With<Camera>>) {
// ...
}
fn main() {
App::new()
// Much better. This will run every frame.
.add_systems(Update, move_camera);
}Any system that modifies the camera in a user-visible way should be run every render frame. The
Update schedule is a good choice for this, but it notably runs after FixedUpdate. You can
use the RunFixedMainLoop schedule with the RunFixedMainLoopSystem::BeforeFixedMainLoop
system set to run a system before FixedUpdate:
fn rotate_camera(mut query: Query<&mut Transform, With<Camera>>) {
// ...
}
fn main() {
App::new()
// In 3D games it is common for the player to move in the direction of the camera.
// Because of this, we must rotate the camera before running the physics logic in
// `FixedUpdate`. This will still run every render frame, though, so there won't be any
// lag!
.add_systems(
RunFixedMainLoop,
rotate_camera.in_set(RunFixedMainLoopSystems::BeforeFixedMainLoop),
);
}For more information, check out the physics in fixed timestep example.