bevyengine / bevyengine/bevy

Audio Sink Creation Delayed and Multiple Sinks Spawned

Open
#13,881 1 comment 0 reactions 0 assignees View on GitHub
A-Audio C-Bug D-Modest S-Needs-Investigation
Dominant language
Rust
Stars
48.2k
Forks
4.8k
Avg merge
3d 22h
Merged PRs (30d)
161

Description

## Bevy version

main aaccbe88aa0d591c9c741f690ab472785c7bac09

## Relevant system information

- Fedora Linux 40 (Workstation Edition)
```
$ uname -a
Linux fedora 6.8.11-300.fc40.x86_64 #1 SMP PREEMPT_DYNAMIC Mon May 27 14:53:33 UTC 2024 x86_64 GNU/Linux
```

## What you did

Tried to play audio if it is not yet playing in `Update` system loop.

```rust
use bevy::audio::Volume;
use bevy::ecs::query::QuerySingleError;
use bevy::prelude::*;

fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_systems(Update, _update_spawn_audio)
.run();
}

#[derive(Component)]
pub struct Beatmap;

fn _update_spawn_audio(
mut commands: Commands,
asset_server: Res,
query: Query<&AudioSink, With>
) {
println!("Query: {}", query.iter().count());

match query.get_single() {
Ok(sink) => {
println!("Ok(sink)");
}
Err(QuerySingleError::NoEntities(_)) => {
println!("Err(QuerySingleError::NoEntities(_))");

commands.spawn((
Beatmap,
AudioBundle {
source: asset_server.load("sounds/loop.ogg"),
settings: PlaybackSettings::LOOP.with_volume(Volume::new(0.1))
},
));
}
Err(QuerySingleError::MultipleEntities(_)) => {
println!("QuerySingleError::MultipleEntities(_)");
}
}
}
```

Output:
```
Query: 0
Err(QuerySingleError::NoEntities(_))
Query: 0
Err(QuerySingleError::NoEntities(_))
Query: 2
QuerySingleError::MultipleEntities(_)
```

After suggestion to use Resources, tried to manually loop audio:
```rust
use bevy::prelude::*;

fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_systems(Update, (
update,
))
.run();
}

#[derive(Resource)]
pub struct Beatmap {
entity: Entity,
}

#[derive(Component)]
pub struct BeatmapAudio;

fn update(
mut commands: Commands,
asset_server: Res,
beatmap: Option>,
query_sink: Query<&AudioSink, With>,
) {
match beatmap {
Some(beatmap) => {
if query_sink.iter().count() >= 2 {
println!("bug: sink count: {:?}", query_sink.iter().count());
}
if query_sink.iter().count() == 0 {
commands.remove_resource::();
}
}
None => {
let entity = commands.spawn((
BeatmapAudio,
AudioBundle {
source: asset_server.load("sounds/tss.wav"),
settings: PlaybackSettings::DESPAWN
},
)).id();
commands.insert_resource(Beatmap {
entity,
});
}
}
}
```

Output:
```
bug: sink count: 2
...
```

## What went wrong

- Expected that audio sink is created immediately.
- Instead, sink is created 2 frames later.
- Expected that it is possible to manually loop the audio.
- Instead, 2 sinks created.

## Additional information

Related discussions:
- Discord: https://discord.com/channels/691052431525675048/1251696503437791272
- Reddit: https://www.reddit.com/r/bevy/comments/1dgw4im/how_to_immediately_spawn_entity_for_a_system_with/

Contributor guide

Open the contributing guide

Research direction

Start by reproducing the two examples in the issue, focusing on the Update system and the reported two-frame delay. Trace when the spawned AudioBundle becomes queryable and when AudioSink entities are created. Done means the sink is available without the unexpected delay and repeated checks do not create multiple sinks.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
game-dev
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.