112 lines
4.1 KiB
C#
112 lines
4.1 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using Code.Infrastructure.Configs;
|
|
using Code.Infrastructure.Utils;
|
|
using Cysharp.Threading.Tasks;
|
|
using ObservableCollections;
|
|
using Reflex.Core;
|
|
using UnityEngine;
|
|
using UnityEngine.ResourceManagement.AsyncOperations;
|
|
using UnityEngine.ResourceManagement.ResourceProviders;
|
|
using UnityEngine.SceneManagement;
|
|
|
|
namespace Code.Infrastructure.SceneLoader
|
|
{
|
|
using UnityEngine.AddressableAssets;
|
|
|
|
public interface ISceneLoader
|
|
{
|
|
UniTask LoadSceneAsync(SceneId id, LoadSceneMode loadMode, bool setActive, Action<Scene, ContainerBuilder> extraInstall = null, Action<Scene, ContainerBuilder> overrideParent = null);
|
|
Scene GetScene(SceneId id);
|
|
UniTask UnloadSceneAsync(SceneId id);
|
|
}
|
|
|
|
public interface ISceneContainerManager
|
|
{
|
|
ObservableDictionary<SceneId, Container> ScenesContainers { get; }
|
|
}
|
|
|
|
public interface ICustomSceneManagerInitializer
|
|
{
|
|
UniTask LoadConfigs();
|
|
}
|
|
|
|
public class CustomCustomSceneManager : IDisposable, ISceneLoader, ISceneContainerManager,
|
|
ICustomSceneManagerInitializer
|
|
{
|
|
private AsyncOperationHandle<IList<SceneInfo>> _loadHandle;
|
|
private AsyncOperationHandle<IList<SceneInfo>> _configHandle;
|
|
private readonly string _configsLabel;
|
|
|
|
public ObservableDictionary<SceneId, Container> ScenesContainers { get; } = new();
|
|
|
|
private Dictionary<SceneId, SceneInfo> _sceneInfos = new();
|
|
private Dictionary<SceneId, AsyncOperationHandle<SceneInstance>> _loadedScenes = new();
|
|
|
|
public CustomCustomSceneManager(IConfigLocator configLocator)
|
|
{
|
|
_configsLabel = configLocator.TryGetManyConfigAssetReferences<SceneInfo>();
|
|
}
|
|
|
|
// Киська
|
|
// TODO При загрузке нескольких сцен сразу может быть неприятность
|
|
public async UniTask LoadSceneAsync(
|
|
SceneId id,
|
|
LoadSceneMode loadMode,
|
|
bool setActive,
|
|
Action<Scene, ContainerBuilder> extraInstall = null,
|
|
Action<Scene, ContainerBuilder> overrideParent = null)
|
|
{
|
|
if (loadMode == LoadSceneMode.Single)
|
|
for (var i = 0; i < _loadedScenes.Count; i++)
|
|
UnloadSceneAsync(_loadedScenes.Keys.ToList()[i]).Forget();
|
|
|
|
if (extraInstall != null) ContainerScope.OnSceneContainerBuilding += extraInstall;
|
|
if (overrideParent != null) ContainerScope.OnSceneContainerBuilding += overrideParent;
|
|
|
|
_loadedScenes.Add(id, Addressables.LoadSceneAsync(_sceneInfos[id].SceneAsset, LoadSceneMode.Additive));
|
|
|
|
await _loadedScenes[id];
|
|
|
|
if (extraInstall != null) ContainerScope.OnSceneContainerBuilding -= extraInstall;
|
|
if (overrideParent != null) ContainerScope.OnSceneContainerBuilding -= overrideParent;
|
|
|
|
if (setActive) SceneManager.SetActiveScene(_loadedScenes[id].Result.Scene);
|
|
}
|
|
|
|
public Scene GetScene(SceneId id) => _loadedScenes[id].Result.Scene;
|
|
|
|
public async UniTask UnloadSceneAsync(SceneId id)
|
|
{
|
|
await Addressables.UnloadSceneAsync(_loadedScenes[id]);
|
|
_loadedScenes.Remove(id);
|
|
}
|
|
|
|
|
|
public async UniTask LoadConfigs()
|
|
{
|
|
if (!await AddressablesUtilities.CheckLabelExists(_configsLabel)) return;
|
|
|
|
_configHandle =
|
|
Addressables.LoadAssetsAsync<SceneInfo>(_configsLabel, OnSceneConfigLoaded,
|
|
Addressables.MergeMode.Union);
|
|
|
|
await _configHandle.ToUniTask();
|
|
}
|
|
|
|
private void OnSceneConfigLoaded(SceneInfo sceneInfoConfig)
|
|
{
|
|
SceneInfo sceneInfo = ScriptableObject.CreateInstance<SceneInfo>();
|
|
sceneInfo.SceneId = sceneInfoConfig.SceneId;
|
|
sceneInfo.SceneAsset = sceneInfoConfig.SceneAsset;
|
|
|
|
_sceneInfos.Add(sceneInfoConfig.SceneId, sceneInfo);
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
if(_configHandle.IsValid()) Addressables.Release(_configHandle);
|
|
}
|
|
}
|
|
} |