Mutating (or Inserting) pre-existing Components in Observers silently fails with stale Component data
- Dominant language
- Rust
- Stars
- 48.2k
- Forks
- 4.8k
- Avg merge
- 3d 22h
- Merged PRs (30d)
- 161
Description
## Bevy version
* bevy 0.16-rc.4
* bevy 0.15
This issue occurs in both 0.16 and 0.15 so I haven't added it to a milestone since it seems pre-existing.
## What you did
Repro repo: https://github.com/ChristopherBiscardi/scene-observer-bug
This repo uses some gltf content (small, but just a json blob so minimized here)
```json
{
"asset": {
"generator": "Khronos glTF Blender I/O v4.4.55",
"version": "2.0"
},
"scene": 0,
"scenes": [
{
"name": "Scene",
"nodes": [0]
}
],
"nodes": [
{
"camera": 0,
"name": "Camera",
"rotation": [
-0.20997299253940582, 0.3857799470424652, 0.09062844514846802,
0.8937962055206299
],
"translation": [7.358891487121582, 4.958309173583984, 6.925790786743164]
}
],
"cameras": [
{
"name": "Camera",
"perspective": {
"aspectRatio": 1.7777777777777777,
"yfov": 0.39959648408210363,
"zfar": 100,
"znear": 0.10000000149011612
},
"type": "perspective"
}
]
}
```
The scene only contains a camera. (I have also seen this issue with PointLights).
An observer listens to the `OnAdd` event for the `Camera` component and tries to mutate it to enable `hdr`.
```rust
app.add_observer(
|trigger: Trigger,
mut cameras: Query<&mut Camera>,
mut commands: Commands|
-> Result {
dbg!(&trigger.target());
let mut camera = cameras.get_mut(trigger.target())?;
// This hdr value does not persist
camera.hdr = true;
commands.entity(trigger.target()).insert(Bloom::default());
// perhaps you think this might work instead;
// it does not, but will trigger an OnInsert with the new value
// .insert(Camera {
// hdr: true,
// ..default()
// });
Ok(())
},
);
```
By contrast, a system run in response to input *can* change this value.
## What went wrong
The `Camera` component `OnAdd` fires, and the value is modified but this new value is not present in the actual inserted Component value. The `hdr` value is always false.
If you try to "override" the `Camera` component by wholly inserting a new one it also does not persist. Additionally, if the event is switched to `OnInsert` this causes a stack overflow (as expected) and the hdr value reads as true in future `OnInsert` iterations. This means the `OnInsert` is seeing the new Component value with `hdr: true`, but the final value in the scene is using the old, original value.
## Additional information
*new* components are successfully inserted. For example, the `Bloom` component used in the reproduction.
Actual Output does *not* have hdr

Expected output *should* have hdr

Contributor guide
Assessment
This issue has not been assessed yet.