// C# using Managers; // 确保日志命名空间正确 using System.Collections; using System.Collections.Generic; // 新增,用于List using TMPro; using UnityEngine; using UnityEngine.SceneManagement; namespace Base { // 请确保你在Unity Editor中将 'projectile' 的Inspector引用从 Gradient 更改为 CustomProgressBar // 或者替换为你实际的进度条组件类型。 // 如果你没有 CustomProgressBar,而想用 Image 或者别的,这些 Progress/Opacity 属性需要大幅修改。 public class Launcher : MonoBehaviour { public GameObject loadingUI; // 假设 CustomProgressBar 是一个自定义组件,其 API 与原代码使用方式一致 // 如果这里是 UnityEngine.UI.Image,需要完全改变 Progress 和 Opacity 的实现 public Gradient progressBar; // 自定义进度条组件 public TMP_Text describeText; // 描述文本 public float duration = 0.5f; // 每个步骤的过渡时间 public float fadeDuration = 2f; // 不透明度渐隐的时间 private float _currentProgressValue = 0f; // 实际的当前进度值(0-1) private Color _initialTextColor; // 原始文本颜色,用于渐隐 private Color _initialProgressBarColor1; // 原始进度条颜色1 private Color _initialProgressBarColor2; // 原始进度条颜色2 // 存储所有需要加载和清理的管理器 private List _managersToLoad; // Progress 属性,更新进度条和颜色 public float Progress { set { // 确保进度值在0到1之间,提高健壮性 _currentProgressValue = Mathf.Clamp01(value); if (progressBar) { // 根据进度值平滑改变进度条的颜色 if (_currentProgressValue < 0.5f) { // 前半段:color2 从初始色渐变到白色 progressBar.color2 = Color.Lerp(_initialProgressBarColor2, Color.white, _currentProgressValue * 2); } else { // 后半段:color2 保持白色,color1 从初始色渐变到白色 progressBar.color2 = Color.white; progressBar.color1 = Color.Lerp(_initialProgressBarColor1, Color.white, (_currentProgressValue - 0.5f) * 2); } progressBar.Refresh(); // 通知自定义进度条组件更新显示 } } get => _currentProgressValue; } // Opacity 属性,更新 UI 元素的透明度 public float Opacity { set { var alpha = Mathf.Clamp01(value); // 确保透明度值在0到1之间 if (progressBar) { // 更新进度条颜色的透明度 Color c1 = progressBar.color1; c1.a = alpha; progressBar.color1 = c1; Color c2 = progressBar.color2; c2.a = alpha; progressBar.color2 = c2; progressBar.Refresh(); } if (describeText) { // 更新描述文本颜色的透明度 // 渐隐时,描述文本的透明度在 Opacity > 0.5f 时才开始渐变可见 var textAlpha = alpha > 0.5f ? Mathf.Lerp(0f, _initialTextColor.a, (alpha - 0.5f) * 2) : 0f; describeText.color = new Color(_initialTextColor.r, _initialTextColor.g, _initialTextColor.b, textAlpha); } } } private void Awake() { // 在 Awake 中初始化管理器列表并注册,确保在 Start 之前完成 _managersToLoad = new List { Logging.UnityLogger.Instance, // UnityLogger的包装器 Managers.DefineManager.Instance, Managers.PackagesImageManager.Instance, Managers.TileManager.Instance, Managers.AffiliationManager.Instance, Managers.ItemResourceManager.Instance // 当未来有新的管理器时,只需在这里添加 Managers.NewManager.Instance }; // 缓存UI的初始颜色,以便后续操作或重置 if (describeText != null) { _initialTextColor = describeText.color; } if (progressBar != null) { _initialProgressBarColor1 = progressBar.color1; _initialProgressBarColor2 = progressBar.color2; } else { Debug.LogWarning("CustomProgressBar component not assigned to Launcher. Progress bar display may not work."); } } private void Start() { // 如果 Program.Instance.needLoad 为 true,表示需要完整的(重新)加载流程 // 否则,如果不需要加载,直接禁用UI并返回 if (!Program.Instance.needLoad) { loadingUI.SetActive(false); return; } // 根据 Program.Instance.needLoad 的含义(需要重载), // 在开始新的加载流程之前,先清理所有可能存在的旧管理器状态。 // 这确保了每次需要加载时,系统都处于一个干净的初始状态。 ClearAllManagers(); // <--- 关键修改:在Load()之前调用ClearAllManagers() // 初始化设置 Base.Setting.Instance.Init(); #if !DEBUG // 在非DEBUG模式下,从设置中获取过渡时间 duration = Base.Setting.Instance.CurrentSettings.progressStepDuration; fadeDuration = Base.Setting.Instance.CurrentSettings.exitAnimationDuration; #endif Load(); // 启动加载流程(内部会调用LoadAllManagers) Program.Instance.needLoad = false; // 加载完成后重置标志 } /// /// 启动游戏的加载流程。 /// public void Load() { loadingUI.SetActive(true); // 激活加载UI Progress = 0f; // 重置进度 Opacity = 1f; // 重置透明度为完全不透明 StartCoroutine(LoadAllManagers()); } /// /// 清理所有管理器,然后重新加载。用于游戏重载或场景切换后需要重新初始化所有数据的情况。 /// public void Reload() { Debug.Log("Performing a full reload of all managers..."); StopAllCoroutines(); // 停止当前所有正在运行的加载协程,避免冲突 ClearAllManagers(); // 清理所有管理器 Load(); // 重新加载游戏数据 } /// /// 遍历所有已注册的管理器并调用它们的 Clear 方法。 /// private void ClearAllManagers() { foreach (var manager in _managersToLoad) { try { manager.Clear(); } catch (System.Exception ex) { Debug.LogError($"Error clearing manager {manager.StepDescription}: {ex.Message}\n{ex.StackTrace}"); } } } /// /// 协程:按顺序加载所有管理器。 /// private IEnumerator LoadAllManagers() { for (var i = 0; i < _managersToLoad.Count; i++) { var manager = _managersToLoad[i]; // 更新描述文本,从管理器实例中获取 if (describeText != null) { describeText.text = manager.StepDescription; } // 计算当前阶段的目标进度 var targetProgress = (float)(i + 1) / _managersToLoad.Count; // 平滑过渡进度条到下一个目标进度 yield return SmoothTransitionTo(targetProgress); // 初始化对应的管理器,并进行异常处理 yield return InitializeManagerSafely(manager); // 模拟耗时,如果管理器Init方法本身很快,可以 uncomment // yield return new WaitForSeconds(0.1f); } // 所有管理器加载完成后的处理 if (describeText != null) { describeText.text = "加载完成!"; } Progress = 1f; // 确保进度条最终达到100% // 开始渐隐效果 yield return FadeOutProgressBar(); // 所有加载和动画结束后,可以考虑卸载加载UI,或跳转到主场景 // ToScene("MainGameScene"); // 如果有需要,在这里跳转到主游戏场景 } /// /// 尝试安全地初始化单个管理器,并捕获任何异常。 /// /// 要初始化的管理器实例。 private IEnumerator InitializeManagerSafely(ILaunchManager manager) { var initSuccess = false; System.Exception initException = null; try { manager.Init(); // 调用管理器的 Init 方法 initSuccess = true; } catch (System.Exception ex) { initException = ex; // 捕获异常 } if (!initSuccess && initException != null) { // 记录错误日志 Debug.LogError($"初始化管理器 '{manager.StepDescription}' 时出错: {initException.Message}\n{initException.StackTrace}"); if (describeText != null) { describeText.text = $"{manager.StepDescription} (初始化失败)"; } // 这里可以添加更复杂的错误处理,例如显示错误弹窗,或者重试逻辑 // yield break; // 如果错误严重,可以选择停止后续加载 } yield return null; // 确保协程继续执行,即使没有做任何事 } /// /// 协程:平滑过渡进度条到指定的目标进度。 /// /// 目标进度值 (0-1)。 private IEnumerator SmoothTransitionTo(float targetProgress) { var startProgress = _currentProgressValue; // 获取当前进度作为起始点 var elapsedTime = 0f; while (elapsedTime < duration) { elapsedTime += Time.deltaTime; // 使用 SmoothStep 实现更自然的加速和减速过渡效果 var t = Mathf.SmoothStep(0f, 1f, elapsedTime / duration); Progress = Mathf.Lerp(startProgress, targetProgress, t); yield return null; } Progress = targetProgress; // 确保最终进度精确达到目标值 } /// /// 协程:渐隐加载UI的透明度。 /// private IEnumerator FadeOutProgressBar() { var elapsedTime = 0f; while (elapsedTime < fadeDuration) { elapsedTime += Time.deltaTime; // 使用 SmoothStep 实现平滑渐隐 var t = Mathf.SmoothStep(0f, 1f, elapsedTime / fadeDuration); Opacity = 1f - t; // 透明度从 1 线性渐变到 0 yield return null; } Opacity = 0f; // 确保最终不透明度为 0 loadingUI.SetActive(false); // 完全隐藏加载UI } /// /// 静态方法:加载指定名称的场景。 /// /// 要加载的场景名称。 public static void ToScene(string scene) { SceneManager.LoadScene(scene); } } }