using System; using System.Collections.Generic; using System.Linq; using Code.Infrastructure.Configs; using Code.Infrastructure.EventBus; using Code.Infrastructure.Generators; using Cysharp.Threading.Tasks; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.ResourceManagement.AsyncOperations; using UnityEngine.ResourceManagement.ResourceProviders; using UnityEngine.SceneManagement; namespace Code.Infrastructure.SceneLoader { [Config("Configs/SceneConfig", true)] public class SceneInfo { [ToConfig] public AssetReference SceneAsset; [ToConfig] public SceneId SceneId; } public partial class SceneLoader : IDisposable { private Dictionary _sceneInfos = new(); private Dictionary _scenesActions = new(); private EventBus.EventBus _eventBus; partial void SetupScenesInfo(); private AsyncOperationHandle> _loadHandle; public SceneLoader(EventBus.EventBus eventBus, IConfigLocator configLocator) { _eventBus = eventBus; LoadConfigs(configLocator.TryGetManyConfigAssetReferences()).Forget(); } // TODO типилище public async UniTaskVoid LoadSceneAsync(SceneId id, LoadSceneMode loadMode) { if (loadMode == LoadSceneMode.Single) for (var i = 0; i < _loadedScenes.Count; i++) UnloadSceneAsync(_loadedScenes.Keys.ToList()[i]).Forget(); _loadedScenes.Add(id, Addressables.LoadSceneAsync(_sceneInfos[id].SceneAsset, loadMode)); await _loadedScenes[id]; _scenesActions[id](); } private Dictionary> _loadedScenes = new(); public Scene GetScene(SceneId id) => _loadedScenes[id].Result.Scene; public async UniTaskVoid UnloadSceneAsync(SceneId id) { await Addressables.UnloadSceneAsync(_loadedScenes[id]); _loadedScenes.Remove(id); } private AsyncOperationHandle> _configHandle; private async UniTaskVoid LoadConfigs(string configReferences) { if ((await Addressables.LoadResourceLocationsAsync(configReferences).Task).Count != 0) { _configHandle = Addressables.LoadAssetsAsync(configReferences, OnSceneConfigLoaded, Addressables.MergeMode.Union); await _configHandle.ToUniTask(); SetupScenesInfo(); } _eventBus.RaiseEvent(h => h.SceneConfigsLoaded()); } private void OnSceneConfigLoaded(SceneInfoConfig sceneInfoConfig) { SceneInfo sceneInfo = new(); sceneInfo.SceneId = sceneInfoConfig.SceneId; sceneInfo.SceneAsset = sceneInfoConfig.SceneAsset; _sceneInfos.Add(sceneInfoConfig.SceneId, sceneInfo); } public void Dispose() { if(_configHandle.IsValid()) _configHandle.Release(); } } public interface ISceneConfigsLoadedHandle : IGlobalSubscriber { void SceneConfigsLoaded(); } public interface ILoadedSceneHandle : IGlobalSubscriber { void SceneLoaded(SceneId sceneId); } }