using System; using System.Collections.Generic; using Code.Infrastructure.Configs; using Code.Infrastructure.Utils; using Cysharp.Threading.Tasks; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.ResourceManagement.AsyncOperations; namespace Code.Infrastructure.Particles { public interface IParticleLoader { UniTask LoadParticleSystems(ParticlePartition partition); void ReleaseParticles(ParticlePartition partition); void Dispose(); } public interface IParticleLoaderInitializer { UniTask LoadConfigs(); } public class ParticleLoader : IParticleLoader, IParticleLoaderInitializer, IDisposable { private readonly string _label; private Dictionary> ParticleInfos { get; } = new(); private readonly Dictionary>> _particleSystemHandles = new(); private AsyncOperationHandle> _configsHandle; private readonly IParticlePoolManagerForFabric _poolManagerForFabric; public ParticleLoader(IConfigLocator configLocator, IParticlePoolManagerForFabric poolManagerForFabric) { _poolManagerForFabric = poolManagerForFabric; _label = configLocator.TryGetManyConfigAssetReferences(); for (var i = 0; i < typeof(ParticlePartition).GetEnumValues().Length; i++) { ParticleInfos.Add((ParticlePartition)i, new Dictionary()); _particleSystemHandles.Add((ParticlePartition)i, new Dictionary>()); } } public async UniTask LoadConfigs() { if (!await AddressablesUtilities.CheckLabelExists(_label)) return; _configsHandle = Addressables.LoadAssetsAsync(_label); await _configsHandle.ToUniTask(); foreach (var config in _configsHandle.Result) ParticleInfos[config.particlePartition].Add(config.particleId, config); } public async UniTask LoadParticleSystems(ParticlePartition partition) { foreach (var particleInfo in ParticleInfos[partition]) if (!_particleSystemHandles[partition].ContainsKey(particleInfo.Key)) _particleSystemHandles[partition].Add(particleInfo.Key, Addressables.LoadAssetAsync(particleInfo.Value.particleSystem)); else _particleSystemHandles[partition][particleInfo.Key] = Addressables.LoadAssetAsync(particleInfo.Value.particleSystem); foreach (var handle in _particleSystemHandles[partition]) await handle.Value.ToUniTask(); foreach (var particleInfo in ParticleInfos[partition]) _poolManagerForFabric.CreatePoolOfParticles( particleInfo.Value, _particleSystemHandles[partition][particleInfo.Key].Result.GetComponent() ); } public void ReleaseParticles(ParticlePartition partition) { if (_particleSystemHandles[partition].Count == 0) return; foreach (var handle in _particleSystemHandles[partition]) { _poolManagerForFabric.DeletePoolOfParticles(partition, handle.Key); Addressables.Release(handle.Value); } _particleSystemHandles[partition].Clear(); } public void Dispose() { foreach (var handles in _particleSystemHandles) { foreach (var handle in handles.Value) { _poolManagerForFabric.DeletePoolOfParticles(handles.Key, handle.Key); handle.Value.Release(); } } _particleSystemHandles.Clear(); if (_configsHandle.IsValid()) _configsHandle.Release(); } } }