using AlicizaX.Event.Runtime; using System; using System.Collections.Generic; using AlicizaX.Resource.Runtime; using Cysharp.Threading.Tasks; using AlicizaX.Runtime; using UnityEngine; using UnityEngine.SceneManagement; using YooAsset; namespace AlicizaX.Scene.Runtime { /// /// 场景组件。 /// [DisallowMultipleComponent] [AddComponentMenu("Game Framework/Scene")] public sealed class SceneComponent : GameFrameworkComponent { private const int DefaultPriority = 0; private IGameSceneManager _gameSceneManager = null; private IResourceManager _resourceManager = null; private EventComponent m_EventComponent = null; private readonly SortedDictionary m_SceneOrder = new SortedDictionary(StringComparer.Ordinal); private Camera m_MainCamera = null; private UnityEngine.SceneManagement.Scene m_GameFrameworkScene = default(UnityEngine.SceneManagement.Scene); [SerializeField] private bool m_EnableLoadSceneUpdateEvent = true; [SerializeField] private bool m_EnableLoadSceneDependencyAssetEvent = true; /// /// 获取当前场景主摄像机。 /// public Camera MainCamera { get { return m_MainCamera; } } /// /// 游戏框架组件初始化。 /// protected override void Awake() { ImplementationComponentType = Utility.Assembly.GetType(componentType); InterfaceComponentType = typeof(IGameSceneManager); base.Awake(); _gameSceneManager = SysModuleCenter.GetModule(); if (_gameSceneManager == null) { Log.Fatal("Scene manager is invalid."); return; } _gameSceneManager.LoadSceneSuccess += OnLoadGameSceneSuccess; _gameSceneManager.LoadSceneFailure += OnLoadGameSceneFailure; if (m_EnableLoadSceneUpdateEvent) { _gameSceneManager.LoadSceneUpdate += OnLoadGameSceneUpdate; } if (m_EnableLoadSceneDependencyAssetEvent) { // _gameSceneManager.LoadSceneDependencyAsset += OnLoadGameSceneDependencyAsset; } _gameSceneManager.UnloadSceneSuccess += OnUnloadGameSceneSuccess; _gameSceneManager.UnloadSceneFailure += OnUnloadGameSceneFailure; m_GameFrameworkScene = UnityEngine.SceneManagement.SceneManager.GetSceneAt(0); if (!m_GameFrameworkScene.IsValid()) { Log.Fatal("Game Framework scene is invalid."); return; } } private void Start() { BaseComponent baseComponent = GameEntry.GetComponent(); if (baseComponent == null) { Log.Fatal("Base component is invalid."); return; } m_EventComponent = GameEntry.GetComponent(); if (m_EventComponent == null) { Log.Fatal("Event component is invalid."); return; } _resourceManager = SysModuleCenter.GetModule(); if (_resourceManager == null) { Log.Fatal("Asset Manager is invalid."); return; } _gameSceneManager.SetResourceManager(_resourceManager); } /// /// 获取场景名称。 /// /// 场景资源名称。 /// 场景名称。 public static string GetSceneName(string sceneAssetName) { if (string.IsNullOrEmpty(sceneAssetName)) { Log.Error("Scene asset name is invalid."); return null; } int sceneNamePosition = sceneAssetName.LastIndexOf('/'); if (sceneNamePosition + 1 >= sceneAssetName.Length) { Log.Error("Scene asset name '{0}' is invalid.", sceneAssetName); return null; } string sceneName = sceneAssetName.Substring(sceneNamePosition + 1); sceneNamePosition = sceneName.LastIndexOf(".unity"); if (sceneNamePosition > 0) { sceneName = sceneName.Substring(0, sceneNamePosition); } return sceneName; } /// /// 获取场景是否已加载。 /// /// 场景资源名称。 /// 场景是否已加载。 public bool SceneIsLoaded(string sceneAssetName) { return _gameSceneManager.SceneIsLoaded(sceneAssetName); } /// /// 获取已加载场景的资源名称。 /// /// 已加载场景的资源名称。 public string[] GetLoadedSceneAssetNames() { return _gameSceneManager.GetLoadedSceneAssetNames(); } /// /// 获取已加载场景的资源名称。 /// /// 已加载场景的资源名称。 public void GetLoadedSceneAssetNames(List results) { _gameSceneManager.GetLoadedSceneAssetNames(results); } /// /// 获取场景是否正在加载。 /// /// 场景资源名称。 /// 场景是否正在加载。 public bool SceneIsLoading(string sceneAssetName) { return _gameSceneManager.SceneIsLoading(sceneAssetName); } /// /// 获取正在加载场景的资源名称。 /// /// 正在加载场景的资源名称。 public string[] GetLoadingSceneAssetNames() { return _gameSceneManager.GetLoadingSceneAssetNames(); } /// /// 获取正在加载场景的资源名称。 /// /// 正在加载场景的资源名称。 public void GetLoadingSceneAssetNames(List results) { _gameSceneManager.GetLoadingSceneAssetNames(results); } /// /// 获取场景是否正在卸载。 /// /// 场景资源名称。 /// 场景是否正在卸载。 public bool SceneIsUnloading(string sceneAssetName) { return _gameSceneManager.SceneIsUnloading(sceneAssetName); } /// /// 获取正在卸载场景的资源名称。 /// /// 正在卸载场景的资源名称。 public string[] GetUnloadingSceneAssetNames() { return _gameSceneManager.GetUnloadingSceneAssetNames(); } /// /// 获取正在卸载场景的资源名称。 /// /// 正在卸载场景的资源名称。 public void GetUnloadingSceneAssetNames(List results) { _gameSceneManager.GetUnloadingSceneAssetNames(results); } /// /// 检查场景资源是否存在。 /// /// 要检查场景资源的名称。 /// 场景资源是否存在。 public bool HasScene(string sceneAssetName) { if (string.IsNullOrEmpty(sceneAssetName)) { Log.Error("Scene asset name is invalid."); return false; } if (!sceneAssetName.StartsWith("Assets/", StringComparison.Ordinal) || !sceneAssetName.EndsWith(".unity", StringComparison.Ordinal)) { Log.Error("Scene asset name '{0}' is invalid.", sceneAssetName); return false; } return _gameSceneManager.HasScene(sceneAssetName); } /// /// 加载场景。 /// /// 场景资源名称。 public UniTask LoadScene(string sceneAssetName) { return LoadScene(sceneAssetName, LoadSceneMode.Additive, null); } /// /// 加载场景。 /// /// 场景资源名称。 /// 加载场景资源的优先级。 /// 用户自定义数据。 public UniTask LoadScene(string sceneAssetName, LoadSceneMode sceneMode, object userData = null) { if (string.IsNullOrEmpty(sceneAssetName)) { Log.Error("Scene asset name is invalid."); throw new ArgumentNullException(nameof(sceneAssetName)); } if (!sceneAssetName.StartsWith("Assets/", StringComparison.Ordinal) || !sceneAssetName.EndsWith(".unity", StringComparison.Ordinal)) { Log.Error("Scene asset name '{0}' is invalid.", sceneAssetName); throw new ArgumentException(nameof(sceneAssetName)); } return _gameSceneManager.LoadScene(sceneAssetName, sceneMode, userData); } /// /// 卸载场景。 /// /// 场景资源名称。 /// 用户自定义数据。 public void UnloadScene(string sceneAssetName, object userData = null) { if (string.IsNullOrEmpty(sceneAssetName)) { Log.Error("Scene asset name is invalid."); return; } if (!sceneAssetName.StartsWith("Assets/", StringComparison.Ordinal) || !sceneAssetName.EndsWith(".unity", StringComparison.Ordinal)) { Log.Error("Scene asset name '{0}' is invalid.", sceneAssetName); return; } _gameSceneManager.UnloadScene(sceneAssetName, userData); m_SceneOrder.Remove(sceneAssetName); } /// /// 设置场景顺序。 /// /// 场景资源名称。 /// 要设置的场景顺序。 public void SetSceneOrder(string sceneAssetName, int sceneOrder) { if (string.IsNullOrEmpty(sceneAssetName)) { Log.Error("Scene asset name is invalid."); return; } if (!sceneAssetName.StartsWith("Assets/", StringComparison.Ordinal) || !sceneAssetName.EndsWith(".unity", StringComparison.Ordinal)) { Log.Error("Scene asset name '{0}' is invalid.", sceneAssetName); return; } if (SceneIsLoading(sceneAssetName)) { m_SceneOrder[sceneAssetName] = sceneOrder; return; } if (SceneIsLoaded(sceneAssetName)) { m_SceneOrder[sceneAssetName] = sceneOrder; RefreshSceneOrder(); return; } Log.Error("Scene '{0}' is not loaded or loading.", sceneAssetName); } /// /// 刷新当前场景主摄像机。 /// public void RefreshMainCamera() { m_MainCamera = Camera.main; } private void RefreshSceneOrder() { if (m_SceneOrder.Count > 0) { string maxSceneName = null; int maxSceneOrder = 0; foreach (var sceneOrder in m_SceneOrder) { if (SceneIsLoading(sceneOrder.Key)) { continue; } if (maxSceneName == null) { maxSceneName = sceneOrder.Key; maxSceneOrder = sceneOrder.Value; continue; } if (sceneOrder.Value > maxSceneOrder) { maxSceneName = sceneOrder.Key; maxSceneOrder = sceneOrder.Value; } } if (maxSceneName == null) { SetActiveScene(m_GameFrameworkScene); return; } var scene = UnityEngine.SceneManagement.SceneManager.GetSceneByName(GetSceneName(maxSceneName)); if (!scene.IsValid()) { Log.Error("Active scene '{0}' is invalid.", maxSceneName); return; } SetActiveScene(scene); } else { SetActiveScene(m_GameFrameworkScene); } } private void SetActiveScene(UnityEngine.SceneManagement.Scene activeScene) { var lastActiveScene = UnityEngine.SceneManagement.SceneManager.GetActiveScene(); if (lastActiveScene != activeScene) { UnityEngine.SceneManagement.SceneManager.SetActiveScene(activeScene); m_EventComponent.Fire(this, ActiveSceneChangedEventArgs.Create(lastActiveScene, activeScene)); } RefreshMainCamera(); } private void OnLoadGameSceneSuccess(object sender, LoadSceneSuccessEventArgs eventArgs) { if (!m_SceneOrder.ContainsKey(eventArgs.SceneAssetName)) { m_SceneOrder.Add(eventArgs.SceneAssetName, 0); } m_EventComponent.Fire(this, eventArgs); RefreshSceneOrder(); } private void OnLoadGameSceneFailure(object sender, LoadSceneFailureEventArgs eventArgs) { Log.Warning("Load scene failure, scene asset name '{0}', error message '{1}'.", eventArgs.SceneAssetName, eventArgs.ErrorMessage); m_EventComponent.Fire(this, eventArgs); } private void OnLoadGameSceneUpdate(object sender, LoadSceneUpdateEventArgs eventArgs) { m_EventComponent.Fire(this, eventArgs); } private void OnUnloadGameSceneSuccess(object sender, UnloadSceneSuccessEventArgs eventArgs) { m_EventComponent.Fire(this, eventArgs); m_SceneOrder.Remove(eventArgs.SceneAssetName); RefreshSceneOrder(); } private void OnUnloadGameSceneFailure(object sender, UnloadSceneFailureEventArgs eventArgs) { Log.Warning("Unload scene failure, scene asset name '{0}'.", eventArgs.SceneAssetName); m_EventComponent.Fire(this, eventArgs); } } }