Files
2026-09-20 15:26:03 +03:00

121 lines
4.1 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using Code.Infrastructure.Configs;
using Cysharp.Threading.Tasks;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.Pool;
using UnityEngine.ResourceManagement.AsyncOperations;
using Object = UnityEngine.Object;
namespace Code.Infrastructure.Audio
{
public interface IAudioSourcePoolInitializer
{
UniTask LoadConfigs();
}
public interface IAudioSourcePool
{
AudioSource GetSource(AudioSourceType sourceType);
void ReleaseSource(AudioSource source);
}
public class AudioSourcePool : IAudioSourcePool, IAudioSourcePoolInitializer, IDisposable
{
// The pool holds plain GameObjects (you can swap this for any component type).
private IObjectPool<AudioSource> _pool;
private GameObject _sourcePrefab;
private Dictionary<AudioSourceType, AudioSourceSettings> _settings;
private string _configsLabel;
private AsyncOperationHandle<IList<AudioSourceSettings>> _handles;
private AssetReference _sourcePrefabConfigReference;
private AsyncOperationHandle<AudioSourcePrefab> _prefabConfigHandle;
private AsyncOperationHandle<GameObject> _prefabHandle;
public AudioSourcePool(IConfigLocator configLocator)
{
_configsLabel = configLocator.TryGetManyConfigAssetReferences<AudioSourceSettings>();
_sourcePrefabConfigReference = configLocator.TryGetConfigAssetReference<AudioSourcePrefab>();
}
public async UniTask LoadConfigs()
{
_prefabConfigHandle = Addressables.LoadAssetAsync<AudioSourcePrefab>(_sourcePrefabConfigReference);
_handles = Addressables.LoadAssetsAsync<AudioSourceSettings>(_configsLabel);
await UniTask.WhenAll(
_prefabConfigHandle.ToUniTask(),
_handles.ToUniTask());
_prefabHandle = Addressables.LoadAssetAsync<GameObject>(_prefabConfigHandle.Result.sourcePrefab);
_settings = _handles.Result.ToDictionary(x => x.sourceType);
await _prefabHandle.ToUniTask();
_pool = new ObjectPool<AudioSource>(
createFunc: CreateItem,
// actionOnGet: OnGet,
actionOnRelease: OnRelease,
actionOnDestroy: OnDestroyItem,
collectionCheck: true, // helps catch double-release mistakes
defaultCapacity: 10,
maxSize: 20
);
}
// Creates a new pooled GameObject the first time (and whenever the pool needs more).
private AudioSource CreateItem()
{
var audioSource = Object.Instantiate(_prefabHandle.Result).GetComponent<AudioSource>();
audioSource.name = "PooledAudioSource";
Object.DontDestroyOnLoad(audioSource);
return audioSource;
}
// Called when an item is taken from the pool.
private void OnGet(AudioSource source)
{
//source.gameObject.SetActive(true);
}
// Called when an item is returned to the pool.
private void OnRelease(AudioSource source)
{
if (!source) return;
source.Stop();
source.resource = null;
source.GetComponent<AudioSourceFollower>().FollowTarget = null;
//source.gameObject.SetActive(false);
}
// Called when the pool decides to destroy an item (e.g., above max size).
private void OnDestroyItem(AudioSource source)
{
Object.Destroy(source.gameObject);
}
public AudioSource GetSource(AudioSourceType sourceType)
{
var source = _pool.Get();
source.spatialBlend = _settings[sourceType].spatialBlend;
return source;
}
public void ReleaseSource(AudioSource source) => _pool.Release(source);
public void Dispose()
{
Addressables.Release(_handles);
Addressables.Release(_prefabConfigHandle);
if (_sourcePrefab) Addressables.Release(_sourcePrefab);
}
}
}