[assets] fix Assets being set as 'changed' each frame (#2280)
## Objective - Fixes: #2275 - `Assets` were being flagged as 'changed' each frame regardless of if the assets were actually being updated. ## Solution - Only have `Assets` change detection be triggered when the collection is actually modified. - This includes utilizing `ResMut` further down the stack instead of a `&mut Assets` directly.
This commit is contained in:
parent
f602dcf643
commit
0b67084e10
@ -5,7 +5,7 @@ use crate::{
|
||||
RefChange, RefChangeChannel, SourceInfo, SourceMeta,
|
||||
};
|
||||
use anyhow::Result;
|
||||
use bevy_ecs::system::Res;
|
||||
use bevy_ecs::system::{Res, ResMut};
|
||||
use bevy_log::warn;
|
||||
use bevy_tasks::TaskPool;
|
||||
use bevy_utils::{HashMap, Uuid};
|
||||
@ -466,7 +466,9 @@ impl AssetServer {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn update_asset_storage<T: Asset>(&self, assets: &mut Assets<T>) {
|
||||
// Note: this takes a `ResMut<Assets<T>>` to ensure change detection does not get
|
||||
// triggered unless the `Assets` collection is actually updated.
|
||||
pub(crate) fn update_asset_storage<T: Asset>(&self, mut assets: ResMut<Assets<T>>) {
|
||||
let asset_lifecycles = self.server.asset_lifecycles.read();
|
||||
let asset_lifecycle = asset_lifecycles.get(&T::TYPE_UUID).unwrap();
|
||||
let mut asset_sources_guard = None;
|
||||
|
||||
@ -177,7 +177,11 @@ impl<T: Asset> Assets<T> {
|
||||
mut events: EventWriter<AssetEvent<T>>,
|
||||
mut assets: ResMut<Assets<T>>,
|
||||
) {
|
||||
events.send_batch(assets.events.drain())
|
||||
// Check if the events are empty before calling `drain`.
|
||||
// As `drain` triggers change detection.
|
||||
if !assets.events.is_empty() {
|
||||
events.send_batch(assets.events.drain())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
|
||||
@ -203,7 +203,7 @@ impl<T: Component> Default for AssetLifecycleChannel<T> {
|
||||
/// Updates the [Assets] collection according to the changes queued up by [AssetServer].
|
||||
pub fn update_asset_storage_system<T: Asset + AssetDynamic>(
|
||||
asset_server: Res<AssetServer>,
|
||||
mut assets: ResMut<Assets<T>>,
|
||||
assets: ResMut<Assets<T>>,
|
||||
) {
|
||||
asset_server.update_asset_storage(&mut assets);
|
||||
asset_server.update_asset_storage(assets);
|
||||
}
|
||||
|
||||
@ -342,6 +342,12 @@ impl<T: Component> Events<T> {
|
||||
self.events_b.clear();
|
||||
}
|
||||
|
||||
/// Returns true if there are no events in this collection.
|
||||
#[inline]
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.events_a.is_empty() && self.events_b.is_empty()
|
||||
}
|
||||
|
||||
/// Creates a draining iterator that removes all events.
|
||||
pub fn drain(&mut self) -> impl Iterator<Item = T> + '_ {
|
||||
self.reset_start_event_count();
|
||||
@ -557,4 +563,21 @@ mod tests {
|
||||
.iter(&events)
|
||||
.eq([TestEvent { i: 0 }, TestEvent { i: 1 }].iter()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_events_empty() {
|
||||
let mut events = Events::<TestEvent>::default();
|
||||
assert!(events.is_empty());
|
||||
|
||||
events.send(TestEvent { i: 0 });
|
||||
assert!(!events.is_empty());
|
||||
|
||||
events.update();
|
||||
assert!(!events.is_empty());
|
||||
|
||||
// events are only empty after the second call to update
|
||||
// due to double buffering.
|
||||
events.update();
|
||||
assert!(events.is_empty());
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user