Audio система в процессе

This commit is contained in:
ThomasCharester committed 2025-11-13 12:31:43 +03:00
1 parent b13cf8cfc0
commit 557c4c3dee
10 files changed
+236 -30

No files matched your search

@@ -0,0 +1,23 @@
namespace Code.Audio
{
public enum SFXSounds
{
Crowbar,
Shot357
}
public enum UISounds
{
Crowbar
}
public enum EnemiesSounds
{
Bastard,
Bravo
}
public enum DispatcherSounds
{
Absolutely,
AbsolutelyNot,
AhFreeman
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 907b506ceac843ebb509a8e5298af540
timeCreated: 1762888870
@@ -1,8 +1,11 @@
using System; using System;
using System.Collections.Generic;
using Code.Configs; using Code.Configs;
using Cysharp.Threading.Tasks; using Cysharp.Threading.Tasks;
using UnityEngine;
using UnityEngine.AddressableAssets; using UnityEngine.AddressableAssets;
using UnityEngine.Audio; using UnityEngine.Audio;
using UnityEngine.ResourceManagement.AsyncOperations;
using Object = UnityEngine.Object; using Object = UnityEngine.Object;
namespace Code.Audio namespace Code.Audio
@@ -10,14 +13,30 @@ namespace Code.Audio
public class AudioFactory : IAudioFactory public class AudioFactory : IAudioFactory
{ {
private AssetReference _audioMixerPrefab; private AssetReference _audioMixerPrefab;
private AssetReference _audioSourcePrefab;
private AssetReference[] _peacefulSoundtrack; private AssetReference[] _peacefulSoundtrack;
private AssetReference[] _actionSoundtrack; private AssetReference[] _actionSoundtrack;
private AssetReference[] _menuSoundtrack;
private AssetReference[] _SFX; private AssetReference[] _SFX;
private AssetReference[] _enemies; private AssetReference[] _enemies;
private AssetReference[] _dispatcher; private AssetReference[] _dispatcher;
private AssetReference[] _character; private AssetReference[] _character;
private AsyncOperationHandle<IList<AudioClip>> _menuMusicHandle;
private AsyncOperationHandle<IList<AudioClip>> _actionMusicHandle;
private AsyncOperationHandle<IList<AudioClip>> _peacefulMusicHandle;
private AsyncOperationHandle<IList<AudioClip>> _SFXHandle;
private AsyncOperationHandle<IList<AudioClip>> _enemiesHandle;
private AsyncOperationHandle<IList<AudioClip>> _dispatcherHandle;
public List<AudioClip> PeacefulMusic { get; private set; }
public List<AudioClip> ActionMusic { get; private set; }
public List<AudioClip> MenuMusic { get; private set; }
public List<AudioClip> SFXAudios { get; private set; }
public List<AudioClip> EnemiesAudios { get; private set; }
public List<AudioClip> DispatcherAudios { get; private set; }
public AudioFactory(AudioMixerConfig audioMixerConfig, public AudioFactory(AudioMixerConfig audioMixerConfig,
SoundtrackListConfig soundtrackListConfig, SoundtrackListConfig soundtrackListConfig,
SFXListConfig sfxListConfig, SFXListConfig sfxListConfig,
@@ -26,15 +45,18 @@ namespace Code.Audio
CharacterSoundListConfig characterSoundListConfig) CharacterSoundListConfig characterSoundListConfig)
{ {
_audioMixerPrefab = audioMixerConfig.audioMixerPrefab; _audioMixerPrefab = audioMixerConfig.audioMixerPrefab;
_audioSourcePrefab = audioMixerConfig.audioSourcePrefab;
_peacefulSoundtrack = soundtrackListConfig.peacefulSoundtrack; _peacefulSoundtrack = soundtrackListConfig.peacefulSoundtrack;
_actionSoundtrack = soundtrackListConfig.actionSoundtrack; _actionSoundtrack = soundtrackListConfig.actionSoundtrack;
_actionSoundtrack = soundtrackListConfig.menuSoundtrack;
_SFX = sfxListConfig.SFX; _SFX = sfxListConfig.SFX;
_enemies = enemiesSoundListConfig.enemies; _enemies = enemiesSoundListConfig.enemies;
_dispatcher = dispatcherSoundListConfig.dispatcher; _dispatcher = dispatcherSoundListConfig.dispatcher;
_character = characterSoundListConfig.character; _character = characterSoundListConfig.character;
} }
public async UniTask<AudioMixer> CreateCanvas()
public async UniTask<AudioMixer> CreateMixer()
{ {
AudioMixer audioMixer = (await Addressables.InstantiateAsync(_audioMixerPrefab).ToUniTask()).GetComponent<AudioMixer>(); AudioMixer audioMixer = (await Addressables.InstantiateAsync(_audioMixerPrefab).ToUniTask()).GetComponent<AudioMixer>();
@@ -43,10 +65,108 @@ namespace Code.Audio
return audioMixer; return audioMixer;
} }
public void ReleaseMixer() public async UniTaskVoid LoadAudioSourcePrefab(Action<AudioSource> callback) => callback?.Invoke(await Addressables.LoadAssetAsync<AudioSource>(_audioSourcePrefab));
{
public async UniTaskVoid WarmGameplayMusic(Action callback)
{
_actionMusicHandle = Addressables.LoadAssetsAsync<AudioClip>(_actionSoundtrack, OnActionTrackLoaded);
_peacefulMusicHandle = Addressables.LoadAssetsAsync<AudioClip>(_peacefulSoundtrack, OnPeacefulTrackLoaded);
await UniTask.WhenAll(_actionMusicHandle.ToUniTask(), _peacefulMusicHandle.ToUniTask());
callback?.Invoke();
} }
public void ReleaseGameplayMusic()
{
ActionMusic.Clear();
_actionMusicHandle.Release();
PeacefulMusic.Clear();
_peacefulMusicHandle.Release();
}
public async UniTaskVoid WarmMenuMusic(Action callback)
{
_menuMusicHandle = Addressables.LoadAssetsAsync<AudioClip>(_menuSoundtrack, OnMenuTrackLoaded);
await _menuMusicHandle.ToUniTask();
callback?.Invoke();
}
public void ReleaseMenuMusic()
{
MenuMusic.Clear();
_menuMusicHandle.Release();
}
public async UniTaskVoid WarmSFX(Action callback)
{
_SFXHandle = Addressables.LoadAssetsAsync<AudioClip>(_SFX, OnSFXLoaded);
await _SFXHandle.ToUniTask();
callback?.Invoke();
}
public void ReleaseSFX()
{
SFXAudios.Clear();
_SFXHandle.Release();
}
public async UniTaskVoid WarmEnemies(Action callback)
{
_enemiesHandle = Addressables.LoadAssetsAsync<AudioClip>(_enemies, OnEnemiesLoaded);
await _enemiesHandle.ToUniTask();
callback?.Invoke();
}
public void ReleaseEnemies()
{
EnemiesAudios.Clear();
_enemiesHandle.Release();
}
public async UniTaskVoid WarmDispatcher(Action callback)
{
_dispatcherHandle = Addressables.LoadAssetsAsync<AudioClip>(_dispatcher, OnDispatcherLoaded);
await _dispatcherHandle.ToUniTask();
callback?.Invoke();
}
public void ReleaseDispatcher()
{
DispatcherAudios.Clear();
_dispatcherHandle.Release();
}
private void OnActionTrackLoaded(AudioClip audioClip)
{
ActionMusic.Add(audioClip);
}
private void OnPeacefulTrackLoaded(AudioClip audioClip)
{
PeacefulMusic.Add(audioClip);
}
private void OnMenuTrackLoaded(AudioClip audioClip)
{
MenuMusic.Add(audioClip);
}
private void OnSFXLoaded(AudioClip audioClip)
{
SFXAudios.Add(audioClip);
}
private void OnEnemiesLoaded(AudioClip audioClip)
{
EnemiesAudios.Add(audioClip);
}
private void OnDispatcherLoaded(AudioClip audioClip)
{
DispatcherAudios.Add(audioClip);
}
} }
} }
@@ -1,17 +1,22 @@
using System; using System;
using System.Collections.Generic;
using Code.Configs; using Code.Configs;
using Code.Constants; using Code.Constants;
using Unity.VisualScripting; using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.AddressableAssets; using UnityEngine.AddressableAssets;
using UnityEngine.Audio; using UnityEngine.Audio;
using Random = UnityEngine.Random;
namespace Code.Audio namespace Code.Audio
{ {
public class AudioService : IAudioService, IDisposable public class AudioService : IAudioService
{ {
private IAudioFactory _audioFactory; private IAudioFactory _audioFactory;
private AudioMixer _mixer; private AudioMixer _mixer;
private AudioSource _actionMusicSource;
private AudioSource _peacefulMusicSource;
private AudioMixerGroup _masterGroup, private AudioMixerGroup _masterGroup,
_musicGroup, _musicGroup,
@@ -23,6 +28,10 @@ namespace Code.Audio
_courierGroup, _courierGroup,
_enemiesGroup; _enemiesGroup;
private readonly AudioSourcePool _audioSourcePool = new();
private Dictionary<AudioSnapshotState, AudioMixerSnapshot> _snapshots = new();
public AudioService(AudioFactory audioFactory) public AudioService(AudioFactory audioFactory)
{ {
_audioFactory = audioFactory; _audioFactory = audioFactory;
@@ -30,7 +39,7 @@ namespace Code.Audio
public async void Initialize(Action callback) public async void Initialize(Action callback)
{ {
_mixer = await _audioFactory.CreateCanvas(); _mixer = await _audioFactory.CreateMixer();
MixerCreated(); MixerCreated();
@@ -48,10 +57,53 @@ namespace Code.Audio
_dispatcherGroup = _mixer.FindMatchingGroups(AudioGroups.DispatcherMusicGroup)[0]; _dispatcherGroup = _mixer.FindMatchingGroups(AudioGroups.DispatcherMusicGroup)[0];
_courierGroup = _mixer.FindMatchingGroups(AudioGroups.CourierMusicGroup)[0]; _courierGroup = _mixer.FindMatchingGroups(AudioGroups.CourierMusicGroup)[0];
_enemiesGroup = _mixer.FindMatchingGroups(AudioGroups.EnemiesMusicGroup)[0]; _enemiesGroup = _mixer.FindMatchingGroups(AudioGroups.EnemiesMusicGroup)[0];
_snapshots[AudioSnapshotState.Peaceful] = _mixer.FindSnapshot(AudioGroups.PeacefulSnapshot);
_snapshots[AudioSnapshotState.Action] = _mixer.FindSnapshot(AudioGroups.ActionSnapshot);
_audioFactory.LoadAudioSourcePrefab(_audioSourcePool.Initialize);
InitializeMusicSources();
} }
public void Dispose() private void InitializeMusicSources()
{ {
_actionMusicSource = _audioSourcePool.GetSource();
_actionMusicSource.outputAudioMixerGroup = _actionMusicGroup;
_actionMusicSource.spatialBlend = 0f;
_peacefulMusicSource = _audioSourcePool.GetSource();
_peacefulMusicSource.outputAudioMixerGroup = _peacefulMusicGroup;
_peacefulMusicSource.spatialBlend = 0f;
}
public void PlayRandomGameplayMusic()
{
_peacefulMusicSource.resource = _audioFactory.PeacefulMusic[Random.Range(0, _audioFactory.PeacefulMusic.Count)];
_actionMusicSource.resource =
_audioFactory.ActionMusic[Random.Range(0, _audioFactory.ActionMusic.Count)];
_peacefulMusicSource.Play();
_actionMusicSource.Play();
}
public void TransitToSnapshot(AudioSnapshotState state)
{
_snapshots[state].TransitionTo(1f);
}
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
public void PlaySFX(SFXSounds sfxId, Vector3 position)
{
_audioSourcePool.PlayOneShot(_audioFactory.SFXAudios[(int)sfxId], position, _SFXGroup);
}
public void PlayEnemy(EnemiesSounds enemySoundId, Vector3 position)
{
_audioSourcePool.PlayOneShot(_audioFactory.EnemiesAudios[(int)enemySoundId], position, _enemiesGroup);
}
public void PlayDispatcher(DispatcherSounds dispatcherSoundId)
{
_audioSourcePool.PlayShizo(_audioFactory.DispatcherAudios[(int)dispatcherSoundId], _dispatcherGroup);
} }
} }
} }
@@ -50,7 +50,7 @@ namespace Code.Audio
_snapshots[AudioSnapshotState.Peaceful] = mixer.FindSnapshot(AudioGroups.PeacefulSnapshot); _snapshots[AudioSnapshotState.Peaceful] = mixer.FindSnapshot(AudioGroups.PeacefulSnapshot);
_snapshots[AudioSnapshotState.Action] = mixer.FindSnapshot(AudioGroups.ActionSnapshot); _snapshots[AudioSnapshotState.Action] = mixer.FindSnapshot(AudioGroups.ActionSnapshot);
_audioSourcePool.Initialize(10,prefab); // _audioSourcePool.Initialize(10,prefab);
InitializeMusicSources(); InitializeMusicSources();
} }
@@ -114,26 +114,6 @@ namespace Code.Audio
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed #pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
} }
public enum SFXSounds
{
Crowbar,
Shot357
}
public enum UISounds
{
Crowbar
}
public enum EnemiesSounds
{
Bastard,
Bravo
}
public enum DispatcherSounds
{
Absolutely,
AbsolutelyNot,
AhFreeman
}
} }
@@ -11,7 +11,7 @@ namespace Code.Audio
private IObjectPool<AudioSource> _pool; private IObjectPool<AudioSource> _pool;
private AudioSource _sourcePrefab; private AudioSource _sourcePrefab;
public void Initialize(int count, AudioSource sourcePrefab) public void Initialize(AudioSource sourcePrefab)
{ {
_sourcePrefab = sourcePrefab; _sourcePrefab = sourcePrefab;
@@ -22,7 +22,7 @@ namespace Code.Audio
// actionOnRelease: OnRelease, // actionOnRelease: OnRelease,
actionOnDestroy: OnDestroyItem, actionOnDestroy: OnDestroyItem,
collectionCheck: true, // helps catch double-release mistakes collectionCheck: true, // helps catch double-release mistakes
defaultCapacity: count, defaultCapacity: 10,
maxSize: 20 maxSize: 20
); );
} }
@@ -1,10 +1,30 @@
using System;
using System.Collections.Generic;
using Cysharp.Threading.Tasks; using Cysharp.Threading.Tasks;
using UnityEngine;
using UnityEngine.Audio; using UnityEngine.Audio;
namespace Code.Audio namespace Code.Audio
{ {
public interface IAudioFactory public interface IAudioFactory
{ {
UniTask<AudioMixer> CreateCanvas(); List<AudioClip> PeacefulMusic { get; }
List<AudioClip> ActionMusic { get; }
List<AudioClip> MenuMusic { get; }
List<AudioClip> SFXAudios { get; }
List<AudioClip> EnemiesAudios { get; }
List<AudioClip> DispatcherAudios { get; }
UniTask<AudioMixer> CreateMixer();
UniTaskVoid LoadAudioSourcePrefab(Action<AudioSource> callback);
UniTaskVoid WarmGameplayMusic(Action callback);
void ReleaseGameplayMusic();
UniTaskVoid WarmMenuMusic(Action callback);
void ReleaseMenuMusic();
UniTaskVoid WarmSFX(Action callback);
void ReleaseSFX();
UniTaskVoid WarmEnemies(Action callback);
void ReleaseEnemies();
UniTaskVoid WarmDispatcher(Action callback);
void ReleaseDispatcher();
} }
} }
@@ -1,9 +1,15 @@
using System; using System;
using UnityEngine;
namespace Code.Audio namespace Code.Audio
{ {
public interface IAudioService public interface IAudioService
{ {
void Initialize(Action callback); void Initialize(Action callback);
void PlayRandomGameplayMusic();
void TransitToSnapshot(AudioSnapshotState state);
void PlaySFX(SFXSounds sfxId, Vector3 position);
void PlayEnemy(EnemiesSounds enemySoundId, Vector3 position);
void PlayDispatcher(DispatcherSounds dispatcherSoundId);
} }
} }
@@ -7,5 +7,6 @@ namespace Code.Configs
public class AudioMixerConfig : ScriptableObject public class AudioMixerConfig : ScriptableObject
{ {
public AssetReference audioMixerPrefab; public AssetReference audioMixerPrefab;
public AssetReference audioSourcePrefab;
} }
} }
@@ -8,5 +8,6 @@ namespace Code.Configs
{ {
public AssetReference[] peacefulSoundtrack; public AssetReference[] peacefulSoundtrack;
public AssetReference[] actionSoundtrack; public AssetReference[] actionSoundtrack;
public AssetReference[] menuSoundtrack;
} }
} }