Second commit

This commit is contained in:
ThomasCharester committed 2026-09-20 15:26:03 +03:00
commit 36840f3ad4
999 files changed
+61364

No files matched your search

@@ -0,0 +1,46 @@
using System;
using Code.Infrastructure.Generators;
using UnityEngine;
using UnityEngine.AddressableAssets;
namespace Code.Infrastructure.Particles
{
[CreateAssetMenu(fileName = "ParticleInfo", menuName = "Configs/Particles/ParticleInfo")]
[Config("Configs/Particles/ParticleInfo", true)]
public class ParticleInfo : ScriptableObject
{
public AssetReference particleSystem;
public int particleId;
public ParticlePartition particlePartition;
public int CountInPool;
public ParticlePartitionIDPair PartitionIDPair;
}
[Serializable]
public struct ParticlePartitionIDPair : IEquatable<ParticlePartitionIDPair>
{
public ParticlePartition ParticlePartition;
public int ID;
public ParticlePartitionIDPair(ParticlePartition particlePartition, int id)
{
ParticlePartition = particlePartition;
ID = id;
}
public bool Equals(ParticlePartitionIDPair other)
{
return ParticlePartition == other.ParticlePartition && ID == other.ID;
}
public override bool Equals(object obj)
{
return obj is ParticlePartitionIDPair other && Equals(other);
}
public override int GetHashCode()
{
return HashCode.Combine((int)ParticlePartition, ID);
}
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 7b7578a949deb96ef808e8b285d8e68e
@@ -0,0 +1,110 @@
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<ParticlePartition, Dictionary<int, ParticleInfo>> ParticleInfos { get; } = new();
private readonly Dictionary<ParticlePartition, Dictionary<int, AsyncOperationHandle<GameObject>>>
_particleSystemHandles = new();
private AsyncOperationHandle<IList<ParticleInfo>> _configsHandle;
private readonly IParticlePoolManagerForFabric _poolManagerForFabric;
public ParticleLoader(IConfigLocator configLocator, IParticlePoolManagerForFabric poolManagerForFabric)
{
_poolManagerForFabric = poolManagerForFabric;
_label = configLocator.TryGetManyConfigAssetReferences<ParticleInfo>();
for (var i = 0; i < typeof(ParticlePartition).GetEnumValues().Length; i++)
{
ParticleInfos.Add((ParticlePartition)i, new Dictionary<int, ParticleInfo>());
_particleSystemHandles.Add((ParticlePartition)i,
new Dictionary<int, AsyncOperationHandle<GameObject>>());
}
}
public async UniTask LoadConfigs()
{
if (!await AddressablesUtilities.CheckLabelExists(_label)) return;
_configsHandle = Addressables.LoadAssetsAsync<ParticleInfo>(_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<GameObject>(particleInfo.Value.particleSystem));
else
_particleSystemHandles[partition][particleInfo.Key] =
Addressables.LoadAssetAsync<GameObject>(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<ParticleSystem>()
);
}
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();
}
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 4e0558ddc52d6d69e825887b8be94f10
@@ -0,0 +1,117 @@
using System;
using System.Collections.Generic;
using Reflex.Attributes;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.Pool;
using Object = UnityEngine.Object;
namespace Code.Infrastructure.Particles
{
public class ParticlePool
{
public IObjectPool<ParticleSystem> Pool;
private ParticleInfo _particleInfoConfig;
private ParticleSystem _particleSystemPrefab;
public ParticlePool(ParticleInfo particleInfoConfig, ParticleSystem particleSystemPrefab)
{
_particleSystemPrefab = particleSystemPrefab;
_particleInfoConfig = particleInfoConfig;
Pool = new ObjectPool<ParticleSystem>(
createFunc: CreateItem,
// actionOnGet: OnGet,
actionOnRelease: OnRelease,
actionOnDestroy: OnDestroyItem,
collectionCheck: true, // helps catch double-release mistakes
defaultCapacity: particleInfoConfig.CountInPool,
maxSize: 20
);
}
public ParticleSystem Get() => Pool.Get();
public void Release(ParticleSystem particleSystem) => Pool.Release(particleSystem);
// Creates a new pooled GameObject the first time (and whenever the pool needs more).
private ParticleSystem CreateItem()
{
var particleSystem = Object
.Instantiate(_particleSystemPrefab) // Он уже загружен
.GetComponent<ParticleSystem>();
particleSystem.name = "PooledParticleSystem";
Object.DontDestroyOnLoad(particleSystem);
return particleSystem;
}
// Called when an item is taken from the pool.
private void OnGet(ParticleSystem source)
{
// Настроить если надо
}
// Called when an item is returned to the pool.
private void OnRelease(ParticleSystem particleSystem)
{
if (!particleSystem) return;
particleSystem.Stop();
// Настроить если надо
}
// Called when the pool decides to destroy an item (e.g., above max size).
private void OnDestroyItem(ParticleSystem source)
{
Object.Destroy(source.gameObject);
}
}
public interface IParticlePoolManagerForService
{
ParticleSystem GetParticleSystem(ParticlePartition partition, int id);
void ReleaseParticleSystem(ParticlePartition partition, int id, ParticleSystem particleSystem);
}
public interface IParticlePoolManagerForFabric
{
void CreatePoolOfParticles(ParticleInfo particleInfoConfig, ParticleSystem particleSystemPrefab);
void DeletePoolOfParticles(ParticlePartition partition, int id);
}
public class ParticlePoolManager : IParticlePoolManagerForService, IParticlePoolManagerForFabric
{
// The pool holds plain GameObjects (you can swap this for any component type).
private Dictionary<ParticlePartition, Dictionary<int, ParticlePool>> _poolDictionary = new();
public void CreatePoolOfParticles(ParticleInfo particleInfoConfig, ParticleSystem particleSystemPrefab)
{
if(!_poolDictionary.ContainsKey(particleInfoConfig.particlePartition))
_poolDictionary[particleInfoConfig.particlePartition] = new();
_poolDictionary[particleInfoConfig.particlePartition]
.Add(particleInfoConfig.particleId, new ParticlePool(particleInfoConfig, particleSystemPrefab));
}
public void DeletePoolOfParticles(ParticlePartition partition, int id)
{
_poolDictionary[partition][id].Pool.Clear();
_poolDictionary[partition].Remove(id);
}
public ParticleSystem GetParticleSystem(ParticlePartition partition, int id)
{
var source = _poolDictionary[partition][id].Get();
// Настроить если надо
return source;
}
public void ReleaseParticleSystem(ParticlePartition partition, int id, ParticleSystem particleSystem)
{
if(_poolDictionary[partition].ContainsKey(id)) _poolDictionary[partition][id].Release(particleSystem);
}
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 21ce106fcb48566dc92ae832b09fa268
@@ -0,0 +1,56 @@
using System;
using System.Collections.Generic;
using System.Threading;
using Cysharp.Threading.Tasks;
using Reflex.Attributes;
using UnityEngine;
namespace Code.Infrastructure.Particles
{
public interface IParticleService
{
UniTaskVoid EmitOneShot(ParticlePartitionIDPair pair, int particleCount, Vector3 position, Quaternion rotation);
UniTaskVoid EmitTillCancelled(ParticlePartitionIDPair pair, CancellationToken token, Vector3 position, Quaternion rotation);
}
public class ParticleService : IParticleService
{
[Inject] private IParticlePoolManagerForService _poolManagerForService;
[Inject] private IParticleLoader _particleLoader;
public async UniTaskVoid EmitOneShot(ParticlePartitionIDPair pair, int particleCount, Vector3 position, Quaternion rotation)
{
var particleSystem = _poolManagerForService.GetParticleSystem(pair.ParticlePartition, pair.ID);
particleSystem.transform.position = position;
particleSystem.transform.rotation = rotation;
particleSystem.Emit(particleCount);
await UniTask.WaitWhile(() => particleSystem.particleCount > 0);
_poolManagerForService.ReleaseParticleSystem(pair.ParticlePartition, pair.ID, particleSystem);
}
public async UniTaskVoid EmitTillCancelled(ParticlePartitionIDPair pair, CancellationToken token, Vector3 position, Quaternion rotation)
{
var particleSystem = _poolManagerForService.GetParticleSystem(pair.ParticlePartition, pair.ID);
particleSystem.transform.position = position;
particleSystem.transform.rotation = rotation;
particleSystem.Play();
try
{
await UniTask.WaitUntilCanceled(cancellationToken: token);
}
catch
{
//
}
particleSystem.Stop();
_poolManagerForService.ReleaseParticleSystem(pair.ParticlePartition, pair.ID, particleSystem);
}
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 0a4f2bf7e8fd80581b714c3d32e47f20