Avoid triggering change detection for inputs (#6847)
# Objective Fix #5292. ## Solution Avoid derefencing when clearing to ensure that change detection is not triggered when there is nothing to clear.
This commit is contained in:
		
							parent
							
								
									b37a6ca9a2
								
							
						
					
					
						commit
						0d67c32153
					
				| @ -1,6 +1,9 @@ | |||||||
| use crate::{Axis, Input}; | use crate::{Axis, Input}; | ||||||
| use bevy_ecs::event::{EventReader, EventWriter}; | use bevy_ecs::event::{EventReader, EventWriter}; | ||||||
| use bevy_ecs::system::{Res, ResMut, Resource}; | use bevy_ecs::{ | ||||||
|  |     change_detection::DetectChanges, | ||||||
|  |     system::{Res, ResMut, Resource}, | ||||||
|  | }; | ||||||
| use bevy_reflect::{std_traits::ReflectDefault, FromReflect, Reflect}; | use bevy_reflect::{std_traits::ReflectDefault, FromReflect, Reflect}; | ||||||
| use bevy_utils::{tracing::info, HashMap}; | use bevy_utils::{tracing::info, HashMap}; | ||||||
| use thiserror::Error; | use thiserror::Error; | ||||||
| @ -1160,7 +1163,7 @@ pub fn gamepad_event_system( | |||||||
|     mut events: EventWriter<GamepadEvent>, |     mut events: EventWriter<GamepadEvent>, | ||||||
|     settings: Res<GamepadSettings>, |     settings: Res<GamepadSettings>, | ||||||
| ) { | ) { | ||||||
|     button_input.clear(); |     button_input.bypass_change_detection().clear(); | ||||||
|     for event in raw_events.iter() { |     for event in raw_events.iter() { | ||||||
|         match &event.event_type { |         match &event.event_type { | ||||||
|             GamepadEventType::Connected(_) => { |             GamepadEventType::Connected(_) => { | ||||||
|  | |||||||
| @ -34,6 +34,13 @@ use bevy_ecs::schedule::State; | |||||||
| /// * Call the [`Input::press`] method for each press event.
 | /// * Call the [`Input::press`] method for each press event.
 | ||||||
| /// * Call the [`Input::release`] method for each release event.
 | /// * Call the [`Input::release`] method for each release event.
 | ||||||
| /// * Call the [`Input::clear`] method at each frame start, before processing events.
 | /// * Call the [`Input::clear`] method at each frame start, before processing events.
 | ||||||
|  | ///
 | ||||||
|  | /// Note: Calling `clear` from a [`ResMut`] will trigger change detection.
 | ||||||
|  | /// It may be preferable to use [`DetectChanges::bypass_change_detection`]
 | ||||||
|  | /// to avoid causing the resource to always be marked as changed.
 | ||||||
|  | ///
 | ||||||
|  | ///[`ResMut`]: bevy_ecs::system::ResMut
 | ||||||
|  | ///[`DetectChanges::bypass_change_detection`]: bevy_ecs::change_detection::DetectChanges::bypass_change_detection
 | ||||||
| #[derive(Debug, Clone, Resource, Reflect)] | #[derive(Debug, Clone, Resource, Reflect)] | ||||||
| #[reflect(Default)] | #[reflect(Default)] | ||||||
| pub struct Input<T: Copy + Eq + Hash + Send + Sync + 'static> { | pub struct Input<T: Copy + Eq + Hash + Send + Sync + 'static> { | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| use crate::{ButtonState, Input}; | use crate::{ButtonState, Input}; | ||||||
| use bevy_ecs::{event::EventReader, system::ResMut}; | use bevy_ecs::{change_detection::DetectChanges, event::EventReader, system::ResMut}; | ||||||
| use bevy_reflect::{FromReflect, Reflect}; | use bevy_reflect::{FromReflect, Reflect}; | ||||||
| 
 | 
 | ||||||
| #[cfg(feature = "serialize")] | #[cfg(feature = "serialize")] | ||||||
| @ -41,8 +41,9 @@ pub fn keyboard_input_system( | |||||||
|     mut key_input: ResMut<Input<KeyCode>>, |     mut key_input: ResMut<Input<KeyCode>>, | ||||||
|     mut keyboard_input_events: EventReader<KeyboardInput>, |     mut keyboard_input_events: EventReader<KeyboardInput>, | ||||||
| ) { | ) { | ||||||
|     scan_input.clear(); |     // Avoid clearing if it's not empty to ensure change detection is not triggered.
 | ||||||
|     key_input.clear(); |     scan_input.bypass_change_detection().clear(); | ||||||
|  |     key_input.bypass_change_detection().clear(); | ||||||
|     for event in keyboard_input_events.iter() { |     for event in keyboard_input_events.iter() { | ||||||
|         let KeyboardInput { |         let KeyboardInput { | ||||||
|             scan_code, state, .. |             scan_code, state, .. | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| use crate::{ButtonState, Input}; | use crate::{ButtonState, Input}; | ||||||
| use bevy_ecs::{event::EventReader, system::ResMut}; | use bevy_ecs::{change_detection::DetectChanges, event::EventReader, system::ResMut}; | ||||||
| use bevy_math::Vec2; | use bevy_math::Vec2; | ||||||
| use bevy_reflect::{FromReflect, Reflect}; | use bevy_reflect::{FromReflect, Reflect}; | ||||||
| 
 | 
 | ||||||
| @ -132,7 +132,7 @@ pub fn mouse_button_input_system( | |||||||
|     mut mouse_button_input: ResMut<Input<MouseButton>>, |     mut mouse_button_input: ResMut<Input<MouseButton>>, | ||||||
|     mut mouse_button_input_events: EventReader<MouseButtonInput>, |     mut mouse_button_input_events: EventReader<MouseButtonInput>, | ||||||
| ) { | ) { | ||||||
|     mouse_button_input.clear(); |     mouse_button_input.bypass_change_detection().clear(); | ||||||
|     for event in mouse_button_input_events.iter() { |     for event in mouse_button_input_events.iter() { | ||||||
|         match event.state { |         match event.state { | ||||||
|             ButtonState::Pressed => mouse_button_input.press(event.button), |             ButtonState::Pressed => mouse_button_input.press(event.button), | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 James Liu
						James Liu