From 4865c538b10a388059ea5a190d5e08d9ff3bcbaf Mon Sep 17 00:00:00 2001 From: Wuketuke <59253838+Wuketuke@users.noreply.github.com> Date: Mon, 7 Jul 2025 21:48:57 +0200 Subject: [PATCH] SpatialListener now requires a Transform (#19357) I noticed that the `SpatialListener` asks to have a `Transform` attached. It seemed weird that we didnt just use a require macro, so i went ahead and did that I also tweaked the system that plays audio to use a `&GlobalTransform` instead of an `Option<&GlobalTransform>` --- crates/bevy_audio/src/audio.rs | 34 ++++++++++++++------------- crates/bevy_audio/src/audio_output.rs | 13 +++------- 2 files changed, 21 insertions(+), 26 deletions(-) diff --git a/crates/bevy_audio/src/audio.rs b/crates/bevy_audio/src/audio.rs index 8a4a406acc..0407997565 100644 --- a/crates/bevy_audio/src/audio.rs +++ b/crates/bevy_audio/src/audio.rs @@ -3,6 +3,7 @@ use bevy_asset::{Asset, Handle}; use bevy_ecs::prelude::*; use bevy_math::Vec3; use bevy_reflect::prelude::*; +use bevy_transform::components::Transform; /// The way Bevy manages the sound playback. #[derive(Debug, Clone, Copy, Reflect)] @@ -10,10 +11,10 @@ use bevy_reflect::prelude::*; pub enum PlaybackMode { /// Play the sound once. Do nothing when it ends. /// - /// Note: It is not possible to reuse an `AudioPlayer` after it has finished playing and - /// the underlying `AudioSink` or `SpatialAudioSink` has been drained. + /// Note: It is not possible to reuse an [`AudioPlayer`] after it has finished playing and + /// the underlying [`AudioSink`](crate::AudioSink) or [`SpatialAudioSink`](crate::SpatialAudioSink) has been drained. /// - /// To replay a sound, the audio components provided by `AudioPlayer` must be removed and + /// To replay a sound, the audio components provided by [`AudioPlayer`] must be removed and /// added again. Once, /// Repeat the sound forever. @@ -27,7 +28,7 @@ pub enum PlaybackMode { /// Initial settings to be used when audio starts playing. /// /// If you would like to control the audio while it is playing, query for the -/// [`AudioSink`][crate::AudioSink] or [`SpatialAudioSink`][crate::SpatialAudioSink] +/// [`AudioSink`](crate::AudioSink) or [`SpatialAudioSink`](crate::SpatialAudioSink) /// components. Changes to this component will *not* be applied to already-playing audio. #[derive(Component, Clone, Copy, Debug, Reflect)] #[reflect(Clone, Default, Component, Debug)] @@ -78,10 +79,10 @@ impl Default for PlaybackSettings { impl PlaybackSettings { /// Will play the associated audio source once. /// - /// Note: It is not possible to reuse an `AudioPlayer` after it has finished playing and - /// the underlying `AudioSink` or `SpatialAudioSink` has been drained. + /// Note: It is not possible to reuse an [`AudioPlayer`] after it has finished playing and + /// the underlying [`AudioSink`](crate::AudioSink) or [`SpatialAudioSink`](crate::SpatialAudioSink) has been drained. /// - /// To replay a sound, the audio components provided by `AudioPlayer` must be removed and + /// To replay a sound, the audio components provided by [`AudioPlayer`] must be removed and /// added again. pub const ONCE: PlaybackSettings = PlaybackSettings { mode: PlaybackMode::Once, @@ -164,14 +165,15 @@ impl PlaybackSettings { /// Settings for the listener for spatial audio sources. /// -/// This must be accompanied by `Transform` and `GlobalTransform`. -/// Only one entity with a `SpatialListener` should be present at any given time. +/// This is accompanied by [`Transform`] and [`GlobalTransform`](bevy_transform::prelude::GlobalTransform). +/// Only one entity with a [`SpatialListener`] should be present at any given time. #[derive(Component, Clone, Debug, Reflect)] +#[require(Transform)] #[reflect(Clone, Default, Component, Debug)] pub struct SpatialListener { - /// Left ear position relative to the `GlobalTransform`. + /// Left ear position relative to the [`GlobalTransform`](bevy_transform::prelude::GlobalTransform). pub left_ear_offset: Vec3, - /// Right ear position relative to the `GlobalTransform`. + /// Right ear position relative to the [`GlobalTransform`](bevy_transform::prelude::GlobalTransform). pub right_ear_offset: Vec3, } @@ -182,7 +184,7 @@ impl Default for SpatialListener { } impl SpatialListener { - /// Creates a new `SpatialListener` component. + /// Creates a new [`SpatialListener`] component. /// /// `gap` is the distance between the left and right "ears" of the listener. Ears are /// positioned on the x axis. @@ -203,12 +205,12 @@ impl SpatialListener { pub struct SpatialScale(pub Vec3); impl SpatialScale { - /// Create a new `SpatialScale` with the same value for all 3 dimensions. + /// Create a new [`SpatialScale`] with the same value for all 3 dimensions. pub const fn new(scale: f32) -> Self { Self(Vec3::splat(scale)) } - /// Create a new `SpatialScale` with the same value for `x` and `y`, and `0.0` + /// Create a new [`SpatialScale`] with the same value for `x` and `y`, and `0.0` /// for `z`. pub const fn new_2d(scale: f32) -> Self { Self(Vec3::new(scale, scale, 0.0)) @@ -238,11 +240,11 @@ pub struct DefaultSpatialScale(pub SpatialScale); /// If the handle refers to an unavailable asset (such as if it has not finished loading yet), /// the audio will not begin playing immediately. The audio will play when the asset is ready. /// -/// When Bevy begins the audio playback, an [`AudioSink`][crate::AudioSink] component will be +/// When Bevy begins the audio playback, an [`AudioSink`](crate::AudioSink) component will be /// added to the entity. You can use that component to control the audio settings during playback. /// /// Playback can be configured using the [`PlaybackSettings`] component. Note that changes to the -/// `PlaybackSettings` component will *not* affect already-playing audio. +/// [`PlaybackSettings`] component will *not* affect already-playing audio. #[derive(Component, Reflect)] #[reflect(Component, Clone)] #[require(PlaybackSettings)] diff --git a/crates/bevy_audio/src/audio_output.rs b/crates/bevy_audio/src/audio_output.rs index d02d326501..749b08a3b9 100644 --- a/crates/bevy_audio/src/audio_output.rs +++ b/crates/bevy_audio/src/audio_output.rs @@ -103,7 +103,7 @@ pub(crate) fn play_queued_audio_system( Entity, &AudioPlayer, &PlaybackSettings, - Option<&GlobalTransform>, + &GlobalTransform, ), (Without, Without), >, @@ -118,7 +118,7 @@ pub(crate) fn play_queued_audio_system( return; }; - for (entity, source_handle, settings, maybe_emitter_transform) in &query_nonplaying { + for (entity, source_handle, settings, emitter_transform) in &query_nonplaying { let Some(audio_source) = audio_sources.get(&source_handle.0) else { continue; }; @@ -136,14 +136,7 @@ pub(crate) fn play_queued_audio_system( } let scale = settings.spatial_scale.unwrap_or(default_spatial_scale.0).0; - - let emitter_translation = if let Some(emitter_transform) = maybe_emitter_transform { - (emitter_transform.translation() * scale).into() - } else { - warn!("Spatial AudioPlayer with no GlobalTransform component. Using zero."); - Vec3::ZERO.into() - }; - + let emitter_translation = (emitter_transform.translation() * scale).into(); let sink = match SpatialSink::try_new( stream_handle, emitter_translation,