using System; using System.Collections.Generic; using System.Linq; using Code.Infrastructure.Configs; using Code.Infrastructure.EventBus; using Cysharp.Threading.Tasks; using Reflex.Core; using Reflex.Injectors; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.ResourceManagement.AsyncOperations; using Object = UnityEngine.Object; namespace Code.Example.Platformer.Entity { public interface IPlatformerEnemyFactory { UniTaskVoid WarmEnemy(PlatformerEntityType enemyType); void ReleaseEnemy(PlatformerEntityType racerType); void SpawnEnemy( PlatformerEntityType enemyType, Vector3 position); } public class PlatformerEnemyFactory : IPlatformerEnemyFactory, IDisposable { private EventBus _eventBus; private string _enemyConfigsLabel; private AsyncOperationHandle> _enemyConfigsHandle; private Dictionary> _enemyPrefabsHandle = new(); private Dictionary _enemyConfigs; public PlatformerEnemyFactory(IConfigLocator configLocator, EventBus eventBus) { _eventBus = eventBus; _enemyConfigsLabel = configLocator.TryGetManyConfigAssetReferences(); LoadConfigs().Forget(); } private async UniTaskVoid LoadConfigs() { _enemyConfigsHandle = Addressables.LoadAssetsAsync(_enemyConfigsLabel); await _enemyConfigsHandle.ToUniTask(); _enemyConfigs = _enemyConfigsHandle.Result.ToDictionary(x => x.EntityData.type); _eventBus.RaiseEvent(x => x.PlatformerEnemyFactoryInitialized()); } public async UniTaskVoid WarmEnemy(PlatformerEntityType enemyType) { if (enemyType == PlatformerEntityType.Player) return; if (_enemyPrefabsHandle.ContainsKey(enemyType)) { _eventBus.RaiseEvent(x => x.PlatformerEnemyLoaded(enemyType, null)); return; } UnityEngine.Debug.LogWarning($"Enemy loaded {enemyType}"); _enemyPrefabsHandle.Add(enemyType, Addressables.LoadAssetAsync(_enemyConfigs[enemyType].prefabReference)); await _enemyPrefabsHandle[enemyType].ToUniTask(); var entity = _enemyPrefabsHandle[enemyType].Result.GetComponent(); _eventBus.RaiseEvent(x => x.PlatformerEnemyLoaded(enemyType, entity)); } public void ReleaseEnemy(PlatformerEntityType racerType) { _enemyPrefabsHandle[racerType].Release(); _enemyPrefabsHandle.Remove(racerType); } public void SpawnEnemy( PlatformerEntityType enemyType, Vector3 position) { if (enemyType == PlatformerEntityType.Player) return; var gameObject = Object.Instantiate(_enemyPrefabsHandle[enemyType].Result, position, Quaternion.identity); var entity = gameObject.GetComponent(); entity.SetData(_enemyConfigs[enemyType].EntityData); var health = gameObject.GetComponent(); health.Setup(_enemyConfigs[enemyType].EntityData.maxHealth, _enemyConfigs[enemyType].EntityData.damageRecieveThreshold); GameObjectInjector.InjectObject(gameObject, Container.RootContainer); _eventBus.RaiseEvent(x=>x.PlatformerEnemySpawned(entity)); } public void Dispose() { UnityEngine.Debug.LogWarning($"Enemies released"); foreach (var prefab in _enemyPrefabsHandle) prefab.Value.Release(); _enemyPrefabsHandle.Clear(); _enemyConfigsHandle.Release(); } } public interface IPlatformerEnemyFactoryInitializedHandle : IGlobalSubscriber { public void PlatformerEnemyFactoryInitialized(); } public interface IPlatformerEnemyLoadedHandle : IGlobalSubscriber { public void PlatformerEnemyLoaded(PlatformerEntityType type, Entity entity); } public interface IPlatformerEnemySpawnedHandle : IGlobalSubscriber { public void PlatformerEnemySpawned(Entity entity); } }