Restructured for new direction.

This commit is contained in:
2026-05-12 12:01:09 +01:00
parent 0439b6c1d2
commit c203f836b1
1134 changed files with 125569 additions and 213519 deletions

View File

@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using BriarQueen.Data.Identifiers;
using BriarQueen.Framework.Coordinators.Events;
@@ -23,41 +22,38 @@ namespace BriarQueen.Framework.Managers.Audio
/// - Settings set "base" volumes (in dB) per mixer parameter.
/// - Runtime states (Pause duck, Voice duck) apply "modifiers" (extra dB offsets).
/// - Effective mixer value is always: effectiveDb = baseDb + modifiersDb
/// - UI and Ambience route through SFX channel/group.
/// - SFX pool is transient — new channels are spawned on demand and
/// finished channels are reaped before each play.
/// </summary>
public class AudioManager : IDisposable, IManager
{
private const int INITIAL_AMBIENCE_SOURCES = 3;
private const int INITIAL_SFX_SOURCES = 6;
private const float PAUSE_DUCK_TARGET_DB = -18f;
private const float PAUSE_DUCK_FADE_SECONDS = 0.25f;
private const int INITIAL_SFX_SOURCES = 8;
private const float PAUSE_DUCK_TARGET_DB = -18f;
private const float PAUSE_DUCK_FADE_SECONDS = 0.25f;
private const float DEFAULT_VOICE_DUCK_TARGET_DB = -20f;
private readonly AudioMixer _audioMixer;
private readonly AudioRegistry _audioRegistry;
private readonly AudioMixer _audioMixer;
private readonly AudioRegistry _audioRegistry;
private readonly EventCoordinator _eventCoordinator;
private readonly Dictionary<string, float> _baseDb = new();
private readonly List<GameObject> _createdAudioObjects = new();
private readonly List<AudioSource> _ambienceSources = new();
private readonly List<AudioFileSo> _currentAmbienceTracks = new();
private readonly List<SfxChannel> _sfxChannels = new();
private readonly Dictionary<string, float> _baseDb = new();
private readonly List<GameObject> _createdAudioObjects = new();
private readonly List<SfxChannel> _sfxChannels = new();
private AudioSource _musicSourceA;
private AudioSource _musicSourceB;
private AudioSource _voiceSource;
private AudioSource _uiSource;
private string _activeVoiceSubtitleId;
private string _activeVoiceSubtitleId;
private AudioFileSo _currentMusicTrack;
private CancellationTokenSource _musicDuckCts;
private CancellationTokenSource _musicFadeCts;
private CancellationTokenSource _voiceCts;
private float _musicDuckDbCurrent;
private float _pauseDuckDbCurrent;
private float _musicDuckDbCurrent;
private float _pauseDuckDbCurrent;
private Sequence _musicDuckSequence;
private Sequence _pauseDuckSequence;
@@ -69,8 +65,8 @@ namespace BriarQueen.Framework.Managers.Audio
[Inject]
public AudioManager(AudioMixer mainMixer, AudioRegistry audioRegistry, EventCoordinator eventCoordinator)
{
_audioMixer = mainMixer;
_audioRegistry = audioRegistry;
_audioMixer = mainMixer;
_audioRegistry = audioRegistry;
_eventCoordinator = eventCoordinator;
}
@@ -137,53 +133,41 @@ namespace BriarQueen.Framework.Managers.Audio
}
_createdAudioObjects.Clear();
_ambienceSources.Clear();
_sfxChannels.Clear();
_currentAmbienceTracks.Clear();
_baseDb.Clear();
_musicSourceA = null;
_musicSourceB = null;
_voiceSource = null;
_uiSource = null;
_currentMusicTrack = null;
_activeVoiceSubtitleId = null;
_musicSourceA = null;
_musicSourceB = null;
_voiceSource = null;
_currentMusicTrack = null;
_activeVoiceSubtitleId = null;
_voiceFinishedPublished = false;
Initialized = false;
Initialized = false;
}
// ── Source creation ───────────────────────────────────────────
private void CreateSources()
{
_musicSourceA = CreateAudioSource("Music_Source_A", AudioMixerGroups.MUSIC_GROUP);
_musicSourceB = CreateAudioSource("Music_Source_B", AudioMixerGroups.MUSIC_GROUP);
_voiceSource = CreateAudioSource("Voice_Source", AudioMixerGroups.VOICE_GROUP);
_uiSource = CreateAudioSource("UI_Source", AudioMixerGroups.UI_GROUP);
_voiceSource = CreateAudioSource("Voice_Source", AudioMixerGroups.VOICE_GROUP);
for (var i = 0; i < INITIAL_SFX_SOURCES; i++)
{
var src = CreateAudioSource($"SFX_Source_{i}", AudioMixerGroups.SFX_GROUP);
_sfxChannels.Add(new SfxChannel
{
Source = src,
StartedAtUnscaled = -999f
});
}
for (var i = 0; i < INITIAL_AMBIENCE_SOURCES; i++)
{
_ambienceSources.Add(CreateAudioSource($"Ambience_Source_{i}", AudioMixerGroups.AMBIENCE_GROUP));
_sfxChannels.Add(new SfxChannel { Source = src, StartedAtUnscaled = -999f });
}
}
// ── Volume ────────────────────────────────────────────────────
private void PrimeMixerBaseValues()
{
PrimeBaseFromMixer(AudioMixerParameters.MASTER_VOLUME);
PrimeBaseFromMixer(AudioMixerParameters.MUSIC_VOLUME);
PrimeBaseFromMixer(AudioMixerParameters.SFX_VOLUME);
PrimeBaseFromMixer(AudioMixerParameters.AMBIENCE_VOLUME);
PrimeBaseFromMixer(AudioMixerParameters.VOICE_VOLUME);
PrimeBaseFromMixer(AudioMixerParameters.UI_VOLUME);
}
public void SetVolume(string parameter, float value01)
@@ -194,25 +178,18 @@ namespace BriarQueen.Framework.Managers.Audio
return;
}
var linear = Mathf.Clamp01(value01);
var db = Linear01ToDb(linear);
_baseDb[parameter] = db;
_baseDb[parameter] = Linear01ToDb(Mathf.Clamp01(value01));
ApplyEffectiveVolume(parameter);
}
private static float Linear01ToDb(float linear01)
{
var lin = Mathf.Max(linear01, 0.0001f);
return Mathf.Log10(lin) * 20f;
return Mathf.Log10(Mathf.Max(linear01, 0.0001f)) * 20f;
}
private void PrimeBaseFromMixer(string parameter)
{
if (_audioMixer != null && _audioMixer.GetFloat(parameter, out var db))
_baseDb[parameter] = db;
else
_baseDb[parameter] = 0f;
_baseDb[parameter] = _audioMixer != null && _audioMixer.GetFloat(parameter, out var db) ? db : 0f;
}
private void ApplyAllEffectiveVolumes()
@@ -220,9 +197,7 @@ namespace BriarQueen.Framework.Managers.Audio
ApplyEffectiveVolume(AudioMixerParameters.MASTER_VOLUME);
ApplyEffectiveVolume(AudioMixerParameters.MUSIC_VOLUME);
ApplyEffectiveVolume(AudioMixerParameters.SFX_VOLUME);
ApplyEffectiveVolume(AudioMixerParameters.AMBIENCE_VOLUME);
ApplyEffectiveVolume(AudioMixerParameters.VOICE_VOLUME);
ApplyEffectiveVolume(AudioMixerParameters.UI_VOLUME);
}
private void ApplyEffectiveVolume(string parameter)
@@ -236,8 +211,7 @@ namespace BriarQueen.Framework.Managers.Audio
var effective = baseDb;
if (parameter == AudioMixerParameters.MUSIC_VOLUME ||
parameter == AudioMixerParameters.SFX_VOLUME ||
parameter == AudioMixerParameters.AMBIENCE_VOLUME)
parameter == AudioMixerParameters.SFX_VOLUME)
{
effective += _pauseDuckDbCurrent;
}
@@ -248,10 +222,11 @@ namespace BriarQueen.Framework.Managers.Audio
_audioMixer.SetFloat(parameter, effective);
}
// ── UI stack / pause duck ─────────────────────────────────────
private void OnUIStackChanged(UIStackChangedEvent e)
{
if (!Initialized)
return;
if (!Initialized) return;
if (e.AnyUIOpen)
OnGamePausedInternal().Forget();
@@ -279,20 +254,18 @@ namespace BriarQueen.Framework.Managers.Audio
_pauseDuckSequence = default;
}
seconds = Mathf.Max(0f, seconds);
var from = _pauseDuckDbCurrent;
_pauseDuckSequence = Sequence.Create(useUnscaledTime: true)
.Group(Tween.Custom(
from,
targetDb,
seconds,
Mathf.Max(0f, seconds),
v =>
{
_pauseDuckDbCurrent = v;
ApplyEffectiveVolume(AudioMixerParameters.MUSIC_VOLUME);
ApplyEffectiveVolume(AudioMixerParameters.SFX_VOLUME);
ApplyEffectiveVolume(AudioMixerParameters.AMBIENCE_VOLUME);
},
Ease.OutCubic,
useUnscaledTime: true));
@@ -303,15 +276,13 @@ namespace BriarQueen.Framework.Managers.Audio
public void PauseVoiceSource(bool paused)
{
if (!Initialized || _voiceSource == null)
return;
if (paused)
_voiceSource.Pause();
else
_voiceSource.UnPause();
if (!Initialized || _voiceSource == null) return;
if (paused) _voiceSource.Pause();
else _voiceSource.UnPause();
}
// ── Play ──────────────────────────────────────────────────────
public void Play(string audioName)
{
if (!Initialized)
@@ -344,21 +315,11 @@ namespace BriarQueen.Framework.Managers.Audio
break;
case TrackType.Ambience:
if (!_currentAmbienceTracks.Contains(audioData))
{
_currentAmbienceTracks.Add(audioData);
PlayOnAvailableAmbienceSource(audioData);
}
break;
case TrackType.UIFX:
case TrackType.Sfx:
PlaySfx(audioData);
break;
case TrackType.UIFX:
PlayOneShotAsync(_uiSource, audioData).Forget();
break;
case TrackType.Voice:
PlayVoiceLine(audioData).Forget();
break;
@@ -368,6 +329,8 @@ namespace BriarQueen.Framework.Managers.Audio
DuckMusicAsync(audioData.Clip.length, audioData.FadeTime).Forget();
}
// ── Voice ─────────────────────────────────────────────────────
private async UniTaskVoid PlayVoiceLine(AudioFileSo audioData)
{
if (!Initialized || _voiceSource == null || audioData?.Clip == null)
@@ -377,15 +340,15 @@ namespace BriarQueen.Framework.Managers.Audio
_voiceCts = new CancellationTokenSource();
var token = _voiceCts.Token;
_activeVoiceSubtitleId = SubtitleIdentifiers.Get(audioData.MatchingSubtitleID);
_activeVoiceSubtitleId = SubtitleIdentifiers.Get(audioData.MatchingSubtitleID);
_voiceFinishedPublished = false;
_eventCoordinator.Publish(new VoiceLineStartedEvent(_activeVoiceSubtitleId));
_voiceSource.clip = audioData.Clip;
_voiceSource.pitch = audioData.Pitch;
_voiceSource.volume = audioData.Volume;
_voiceSource.loop = false;
_voiceSource.clip = audioData.Clip;
_voiceSource.pitch = audioData.Pitch;
_voiceSource.volume = audioData.Volume;
_voiceSource.loop = false;
_voiceSource.priority = audioData.Priority;
_voiceSource.Play();
@@ -404,31 +367,210 @@ namespace BriarQueen.Framework.Managers.Audio
private void PublishVoiceFinishedIfNeeded()
{
if (_voiceFinishedPublished)
return;
if (_voiceFinishedPublished) return;
if (!string.IsNullOrEmpty(_activeVoiceSubtitleId))
_eventCoordinator.Publish(new VoiceLineFinishedEvent(_activeVoiceSubtitleId));
_voiceFinishedPublished = true;
_activeVoiceSubtitleId = null;
_activeVoiceSubtitleId = null;
}
public void StopVoice()
{
if (!Initialized) return;
StopAndDispose(ref _voiceCts);
if (_voiceSource != null && _voiceSource.isPlaying)
_voiceSource.Stop();
PublishVoiceFinishedIfNeeded();
}
// ── SFX (transient pool) ──────────────────────────────────────
private void PlaySfx(AudioFileSo audioData)
{
if (!Initialized || audioData == null || audioData.Clip == null)
return;
// Reap finished channels first so we don't accumulate stale entries
ReapFinishedSfxChannels();
// Try to find a free channel from the existing pool
AudioSource src = null;
var channelIndex = -1;
for (var i = 0; i < _sfxChannels.Count; i++)
{
var s = _sfxChannels[i].Source;
if (s != null && !s.isPlaying)
{
src = s;
channelIndex = i;
break;
}
}
// No free channel — spawn a transient one
if (src == null)
{
src = CreateAudioSource($"SFX_Source_Transient_{_sfxChannels.Count}", AudioMixerGroups.SFX_GROUP);
_sfxChannels.Add(new SfxChannel { Source = src, StartedAtUnscaled = -999f });
channelIndex = _sfxChannels.Count - 1;
Debug.Log($"[AudioManager] SFX pool expanded to {_sfxChannels.Count} channels.");
}
src.priority = audioData.Priority;
src.pitch = audioData.Pitch;
src.loop = audioData.Loopable;
src.PlayOneShot(audioData.Clip, audioData.Volume);
_sfxChannels[channelIndex] = new SfxChannel
{
Source = src,
StartedAtUnscaled = Time.unscaledTime
};
}
/// <summary>
/// Removes finished transient channels from the pool to prevent unbounded growth.
/// Preserves the initial pool channels even when idle.
/// </summary>
private void ReapFinishedSfxChannels()
{
for (var i = _sfxChannels.Count - 1; i >= INITIAL_SFX_SOURCES; i--)
{
var src = _sfxChannels[i].Source;
if (src == null || src.isPlaying)
continue;
// Destroy the transient GameObject and remove from pool
if (src.gameObject != null)
{
_createdAudioObjects.Remove(src.gameObject);
Object.Destroy(src.gameObject);
}
_sfxChannels.RemoveAt(i);
}
}
public void StopAllSfx()
{
if (!Initialized) return;
for (var i = _sfxChannels.Count - 1; i >= 0; i--)
{
var src = _sfxChannels[i].Source;
if (src == null) continue;
src.Stop();
// Destroy transient channels, reset initial ones
if (i >= INITIAL_SFX_SOURCES)
{
if (src.gameObject != null)
{
_createdAudioObjects.Remove(src.gameObject);
Object.Destroy(src.gameObject);
}
_sfxChannels.RemoveAt(i);
}
else
{
_sfxChannels[i] = new SfxChannel { Source = src, StartedAtUnscaled = -999f };
}
}
}
// ── Music ─────────────────────────────────────────────────────
public async UniTask CrossfadeMusic(AudioFileSo newTrack, float duration)
{
if (!Initialized || !newTrack || !newTrack.Clip) return;
if (_currentMusicTrack == newTrack) return;
StopAndDispose(ref _musicFadeCts);
_musicFadeCts = new CancellationTokenSource();
var token = _musicFadeCts.Token;
var activeSource = _musicSourceA.isPlaying ? _musicSourceA
: _musicSourceB.isPlaying ? _musicSourceB
: null;
var inactiveSource = activeSource == _musicSourceA ? _musicSourceB : _musicSourceA;
PlayOnSource(inactiveSource, newTrack);
if (activeSource == null)
{
inactiveSource.volume = newTrack.Volume;
_currentMusicTrack = newTrack;
_eventCoordinator.Publish(new MusicTrackChangedEvent(newTrack));
return;
}
duration = Mathf.Max(0.0001f, duration);
var elapsed = 0f;
var startVolume = activeSource.volume;
try
{
while (elapsed < duration)
{
token.ThrowIfCancellationRequested();
var t = elapsed / duration;
activeSource.volume = Mathf.Lerp(startVolume, 0f, t);
inactiveSource.volume = Mathf.Lerp(0f, newTrack.Volume, t);
elapsed += Time.unscaledDeltaTime;
await UniTask.Yield(PlayerLoopTiming.Update, token);
}
activeSource.volume = 0f;
inactiveSource.volume = newTrack.Volume;
}
catch (OperationCanceledException)
{
return;
}
activeSource.Stop();
activeSource.volume = startVolume;
_currentMusicTrack = newTrack;
_eventCoordinator.Publish(new MusicTrackChangedEvent(newTrack));
}
public void StopMusic()
{
if (!Initialized) return;
StopAndDispose(ref _musicFadeCts);
if (_musicSourceA != null) { _musicSourceA.Stop(); _musicSourceA.clip = null; _musicSourceA.volume = 0f; }
if (_musicSourceB != null) { _musicSourceB.Stop(); _musicSourceB.clip = null; _musicSourceB.volume = 0f; }
_currentMusicTrack = null;
}
private async UniTask DuckMusicAsync(float clipLengthSeconds, float fadeTimeSeconds)
{
if (!Initialized)
return;
if (!Initialized) return;
StopAndDispose(ref _musicDuckCts);
_musicDuckCts = new CancellationTokenSource();
var token = _musicDuckCts.Token;
fadeTimeSeconds = Mathf.Max(0.0001f, fadeTimeSeconds);
var duckTarget = DEFAULT_VOICE_DUCK_TARGET_DB;
try
{
await TweenMusicDuckTo(duckTarget, fadeTimeSeconds, token);
await TweenMusicDuckTo(DEFAULT_VOICE_DUCK_TARGET_DB, fadeTimeSeconds, token);
var hold = clipLengthSeconds - fadeTimeSeconds * 2f;
if (hold > 0.01f)
@@ -450,15 +592,13 @@ namespace BriarQueen.Framework.Managers.Audio
_musicDuckSequence = default;
}
seconds = Mathf.Max(0f, seconds);
var from = _musicDuckDbCurrent;
_musicDuckSequence = Sequence.Create(useUnscaledTime: true)
.Group(Tween.Custom(
from,
targetDb,
seconds,
Mathf.Max(0f, seconds),
v =>
{
_musicDuckDbCurrent = v;
@@ -471,258 +611,22 @@ namespace BriarQueen.Framework.Managers.Audio
_musicDuckSequence = default;
}
public async UniTask CrossfadeMusic(AudioFileSo newTrack, float duration)
{
if (!Initialized || !newTrack || !newTrack.Clip)
return;
if (_currentMusicTrack == newTrack)
return;
StopAndDispose(ref _musicFadeCts);
_musicFadeCts = new CancellationTokenSource();
var token = _musicFadeCts.Token;
var activeSource = _musicSourceA.isPlaying
? _musicSourceA
: _musicSourceB.isPlaying
? _musicSourceB
: null;
var inactiveSource = activeSource == _musicSourceA ? _musicSourceB : _musicSourceA;
PlayOnSource(inactiveSource, newTrack);
if (activeSource == null)
{
inactiveSource.volume = newTrack.Volume;
_currentMusicTrack = newTrack;
_eventCoordinator.Publish(new MusicTrackChangedEvent(newTrack));
return;
}
duration = Mathf.Max(0.0001f, duration);
var elapsed = 0f;
var startVolume = activeSource.volume;
try
{
while (elapsed < duration)
{
token.ThrowIfCancellationRequested();
var t = elapsed / duration;
activeSource.volume = Mathf.Lerp(startVolume, 0f, t);
inactiveSource.volume = Mathf.Lerp(0f, newTrack.Volume, t);
elapsed += Time.unscaledDeltaTime;
await UniTask.Yield(PlayerLoopTiming.Update, token);
}
activeSource.volume = 0f;
inactiveSource.volume = newTrack.Volume;
}
catch (OperationCanceledException)
{
return;
}
activeSource.Stop();
activeSource.volume = startVolume;
_currentMusicTrack = newTrack;
_eventCoordinator.Publish(new MusicTrackChangedEvent(newTrack));
}
private void PlaySfx(AudioFileSo audioData)
{
if (!Initialized || audioData == null || audioData.Clip == null)
return;
var channelIndex = GetBestSfxChannelIndex(audioData.Priority);
if (channelIndex < 0 || channelIndex >= _sfxChannels.Count)
return;
var src = _sfxChannels[channelIndex].Source;
if (src == null)
return;
if (src.isPlaying)
src.Stop();
src.priority = audioData.Priority;
src.pitch = audioData.Pitch;
src.PlayOneShot(audioData.Clip, audioData.Volume);
_sfxChannels[channelIndex] = new SfxChannel
{
Source = src,
StartedAtUnscaled = Time.unscaledTime
};
}
private int GetBestSfxChannelIndex(int incomingPriority)
{
for (var i = 0; i < _sfxChannels.Count; i++)
{
var src = _sfxChannels[i].Source;
if (src == null)
continue;
if (!src.isPlaying)
return i;
}
var bestIndex = -1;
var worstPriority = int.MinValue;
var oldestStart = float.MaxValue;
for (var i = 0; i < _sfxChannels.Count; i++)
{
var src = _sfxChannels[i].Source;
if (src == null)
continue;
var p = src.priority;
var started = _sfxChannels[i].StartedAtUnscaled;
if (p > worstPriority || (p == worstPriority && started < oldestStart))
{
worstPriority = p;
oldestStart = started;
bestIndex = i;
}
}
return bestIndex;
}
public void StopAmbience(AudioFileSo audioData)
{
if (!Initialized || !audioData || !audioData.Clip || audioData.Type != TrackType.Ambience)
return;
if (_currentAmbienceTracks.Remove(audioData))
{
foreach (var source in _ambienceSources.Where(s => s != null && s.clip == audioData.Clip))
source.Stop();
}
}
public void StopAllAmbience()
{
if (!Initialized)
return;
foreach (var s in _ambienceSources)
{
if (s != null)
s.Stop();
}
_currentAmbienceTracks.Clear();
}
private void PlayOnAvailableAmbienceSource(AudioFileSo audioData)
{
var source = _ambienceSources.FirstOrDefault(s => s != null && !s.isPlaying);
if (source == null)
{
source = CreateAudioSource(
$"Ambience_Source_{_ambienceSources.Count}",
AudioMixerGroups.AMBIENCE_GROUP);
_ambienceSources.Add(source);
}
PlayOnSource(source, audioData);
}
public void StopMusic()
{
if (!Initialized)
return;
StopAndDispose(ref _musicFadeCts);
if (_musicSourceA != null)
{
_musicSourceA.Stop();
_musicSourceA.clip = null;
_musicSourceA.volume = 0f;
}
if (_musicSourceB != null)
{
_musicSourceB.Stop();
_musicSourceB.clip = null;
_musicSourceB.volume = 0f;
}
_currentMusicTrack = null;
}
public void StopVoice()
{
if (!Initialized)
return;
StopAndDispose(ref _voiceCts);
if (_voiceSource != null && _voiceSource.isPlaying)
_voiceSource.Stop();
PublishVoiceFinishedIfNeeded();
}
public void StopAllSfx()
{
if (!Initialized)
return;
for (var i = 0; i < _sfxChannels.Count; i++)
{
var src = _sfxChannels[i].Source;
if (src == null)
continue;
src.Stop();
_sfxChannels[i] = new SfxChannel
{
Source = src,
StartedAtUnscaled = -999f
};
}
}
// ── Stop all ──────────────────────────────────────────────────
public void StopAllAudio()
{
if (!Initialized)
return;
if (!Initialized) return;
StopMusic();
StopVoice();
StopAllSfx();
StopAllAmbience();
if (_uiSource != null)
_uiSource.Stop();
}
// ── Helpers ───────────────────────────────────────────────────
private static void StopAndDispose(ref CancellationTokenSource cts)
{
if (cts == null)
return;
try
{
cts.Cancel();
}
catch
{
}
if (cts == null) return;
try { cts.Cancel(); } catch { }
cts.Dispose();
cts = null;
}
@@ -733,7 +637,7 @@ namespace BriarQueen.Framework.Managers.Audio
Object.DontDestroyOnLoad(obj);
_createdAudioObjects.Add(obj);
var src = obj.AddComponent<AudioSource>();
var src = obj.AddComponent<AudioSource>();
var group = _audioMixer.FindMatchingGroups(groupName);
if (group != null && group.Length > 0)
@@ -744,28 +648,14 @@ namespace BriarQueen.Framework.Managers.Audio
return src;
}
private async UniTaskVoid PlayOneShotAsync(AudioSource source, AudioFileSo audioData)
{
if (!Initialized || source == null || audioData == null || audioData.Clip == null)
return;
source.priority = audioData.Priority;
source.pitch = audioData.Pitch;
source.PlayOneShot(audioData.Clip, audioData.Volume);
var seconds = audioData.Clip.length / Mathf.Max(audioData.Pitch, 0.0001f);
await UniTask.Delay(TimeSpan.FromSeconds(seconds));
}
private void PlayOnSource(AudioSource source, AudioFileSo audioData)
{
if (!Initialized || source == null || audioData == null)
return;
if (!Initialized || source == null || audioData == null) return;
source.clip = audioData.Clip;
source.loop = audioData.Loopable;
source.volume = audioData.Volume;
source.pitch = audioData.Pitch;
source.clip = audioData.Clip;
source.loop = audioData.Loopable;
source.volume = audioData.Volume;
source.pitch = audioData.Pitch;
source.priority = audioData.Priority;
source.Play();
}
@@ -773,7 +663,7 @@ namespace BriarQueen.Framework.Managers.Audio
private struct SfxChannel
{
public AudioSource Source;
public float StartedAtUnscaled;
public float StartedAtUnscaled;
}
}
}