using System.Collections.Generic; using System.Threading; using Code.Infrastructure.EventBus; using Cysharp.Threading.Tasks; using UnityEngine; using UnityEngine.Audio; namespace Code.Infrastructure.Audio { public interface IAudioService { AudioClip GetClip(AudioNames groupName, int id); void PlayTest(); UniTaskVoid PlayOneShot(AudioNames groupName, int id, Vector3 position = new Vector3(), AudioSourceType sourceType = AudioSourceType.NoBlend, AudioSource audioSource = null); UniTaskVoid PlayRepeatedly(AudioNames groupName, int id, CancellationTokenSource cancellationTokenSource, AudioSourceType sourceType = AudioSourceType.NoBlend, AudioSource audioSource = null); bool CheckClip(AudioNames groupName, int id); } public partial class AudioService : IAudioClipsEventHandle, IAudioService { private EventBus.EventBus _eventBus; private IAudioFactory _audioFactory; private IAudioSourcePool _pool; private Dictionary> _audioClips = new(); private AudioMixer _mixer; private Dictionary _audioMixerGroups = new(); public AudioService(EventBus.EventBus eventBus, IAudioFactory audioFactory, IAudioSourcePool pool) { _eventBus = eventBus; _audioFactory = audioFactory; _pool = pool; _eventBus.Subscribe(this); for (int i = 0; i < typeof(AudioNames).GetEnumValues().Length; i++) _audioClips.Add((AudioNames)i, new Dictionary()); //InitializeMixer(); } private partial void InitializeMixer(); public void PlayTest() { _pool.GetSource(AudioSourceType.NoBlend).PlayOneShot(GetClip(AudioNames.UISounds, 0)); } public async UniTaskVoid PlayOneShot(AudioNames groupName, int id, Vector3 position = new Vector3(), AudioSourceType sourceType = AudioSourceType.NoBlend, AudioSource audioSource = null) { if (!CheckClip(groupName, id)) return; if (!audioSource) audioSource = _pool.GetSource(sourceType); audioSource.transform.position = position; audioSource.PlayOneShot(GetClip(groupName, id)); await UniTask.NextFrame(); await UniTask.WaitUntilValueChanged(audioSource, _ => !audioSource.isPlaying); _pool.ReleaseSource(audioSource); } public async UniTaskVoid PlayRepeatedly(AudioNames groupName, int id, CancellationTokenSource cancellationTokenSource, AudioSourceType sourceType = AudioSourceType.NoBlend, AudioSource audioSource = null) { if (!CheckClip(groupName, id)) return; if (!audioSource) audioSource = _pool.GetSource(sourceType); if(!audioSource.resource) audioSource.resource = GetClip(groupName, id); audioSource.Play(); await UniTask.NextFrame(); var (isCanceled, _) = await UniTask.WaitUntilValueChanged(audioSource, _ => !audioSource.isPlaying, cancellationToken: cancellationTokenSource.Token).SuppressCancellationThrow(); UnityEngine.Debug.LogError("Music skipping"); if (isCanceled) { cancellationTokenSource.Dispose(); _pool.ReleaseSource(audioSource); return; } PlayRepeatedly(groupName, id, cancellationTokenSource, sourceType, audioSource).Forget(); } public AudioClip GetClip(AudioNames groupName, int id) => _audioClips[groupName][id]; public bool CheckClip(AudioNames groupName, int id) => _audioClips[groupName].ContainsKey(id); public void AudioClipsLoaded(AudioNames groupname, Dictionary clips) { _audioClips[groupname] = clips; _eventBus.RaiseEvent(x => x.OnReadyToPlay(groupname)); } public void AudioClipsUnLoaded(AudioNames groupName) { _audioClips[groupName].Clear(); _audioClips[groupName] = null; } } public interface IReadyToPlayHandle : IGlobalSubscriber { void OnReadyToPlay(AudioNames groupName); } }