using System; using System.Collections.Generic; using Cysharp.Threading.Tasks; using UnityEngine.SceneManagement; using YooAsset; namespace TEngine { /// /// 场景管理器。 /// internal class SceneModuleImp : ModuleImp, ISceneModule { private string _currentMainSceneName = string.Empty; private SceneHandle _currentMainScene; private readonly Dictionary _subScenes = new Dictionary(); /// /// 当前主场景名称。 /// public string CurrentMainSceneName => _currentMainSceneName; internal override void Shutdown() { var iter = _subScenes.Values.GetEnumerator(); while (iter.MoveNext()) { SceneHandle subScene = iter.Current; if (subScene != null) { subScene.UnloadAsync(); } } iter.Dispose(); _subScenes.Clear(); _currentMainSceneName = string.Empty; } /// /// 加载场景。 /// /// 场景的定位地址R /// 场景加载模式 /// 加载完毕时是否主动挂起 /// 优先级 /// 加载回调。 /// 加载主场景是否回收垃圾。 /// 加载进度回调。 public SceneHandle LoadScene(string location, LoadSceneMode sceneMode = LoadSceneMode.Single, bool suspendLoad = false, int priority = 100, Action callBack = null, bool gcCollect = true, Action progressCallBack = null) { if (sceneMode == LoadSceneMode.Additive) { if (_subScenes.TryGetValue(location, out SceneHandle subScene)) { Log.Warning($"Could not load subScene while already loaded. Scene: {location}"); return subScene; } subScene = YooAssets.LoadSceneAsync(location, sceneMode, suspendLoad, (uint)priority); if (callBack != null) { subScene.Completed += callBack; } if (progressCallBack != null) { InvokeProgress(subScene, progressCallBack).Forget(); } _subScenes.Add(location, subScene); return subScene; } else { if (_currentMainScene is { IsDone: false }) { Log.Warning($"Could not load MainScene while loading. CurrentMainScene: {_currentMainSceneName}."); return null; } _currentMainSceneName = location; _currentMainScene = YooAssets.LoadSceneAsync(location, sceneMode, suspendLoad, (uint)priority); if (callBack != null) { _currentMainScene.Completed += callBack; } if (progressCallBack != null) { InvokeProgress(_currentMainScene, progressCallBack).Forget(); } GameModule.Resource.ForceUnloadUnusedAssets(gcCollect); return _currentMainScene; } } private async UniTaskVoid InvokeProgress(SceneHandle SceneHandle,Action progress) { if (SceneHandle == null) { return; } while (!SceneHandle.IsDone) { await UniTask.Yield(); progress?.Invoke(SceneHandle.Progress); } } /// /// 激活场景(当同时存在多个场景时用于切换激活场景)。 /// /// 场景资源定位地址。 /// 是否操作成功。 public bool ActivateScene(string location) { if (_currentMainSceneName.Equals(location)) { if (_currentMainScene != null) { return _currentMainScene.ActivateScene(); } return false; } _subScenes.TryGetValue(location, out SceneHandle subScene); if (subScene != null) { return subScene.ActivateScene(); } Log.Warning($"IsMainScene invalid location:{location}"); return false; } /// /// 解除场景加载挂起操作。 /// /// 场景资源定位地址。 /// 是否操作成功。 public bool UnSuspend(string location) { if (_currentMainSceneName.Equals(location)) { if (_currentMainScene != null) { return _currentMainScene.UnSuspend(); } return false; } _subScenes.TryGetValue(location, out SceneHandle subScene); if (subScene != null) { return subScene.UnSuspend(); } Log.Warning($"IsMainScene invalid location:{location}"); return false; } /// /// 是否为主场景。 /// /// 场景资源定位地址。 /// 是否主场景。 public bool IsMainScene(string location) { if (_currentMainSceneName.Equals(location)) { if (_currentMainScene != null) { return _currentMainScene.IsMainScene(); } return true; } _subScenes.TryGetValue(location, out SceneHandle subScene); if (subScene != null) { return subScene.IsMainScene(); } Log.Warning($"IsMainScene invalid location:{location}"); return false; } /// /// 异步卸载子场景。 /// /// 场景资源定位地址。 /// 场景卸载异步操作类。 public UnloadSceneOperation UnloadAsync(string location) { _subScenes.TryGetValue(location, out SceneHandle subScene); if (subScene != null) { if (subScene.SceneObject == default) { Log.Error($"Could not unload Scene while not loaded. Scene: {location}"); return null; } _subScenes.Remove(location); return subScene.UnloadAsync(); } Log.Warning($"UnloadAsync invalid location:{location}"); return null; } /// /// 是否包含场景。 /// /// 场景资源定位地址。 /// 是否包含场景。 public bool IsContainScene(string location) { if (_currentMainSceneName.Equals(location)) { return true; } return _subScenes.TryGetValue(location, out var _); } } }