(client)chore:将维度区分独立,将加载页面独立,降低代码耦合,写了更好看的注释

This commit is contained in:
m0_75251201
2025-08-26 00:11:36 +08:00
parent d8a3daaca8
commit efbf4f824a
22 changed files with 4026 additions and 755 deletions

View File

@ -1,171 +1,293 @@
// C#
using System.Collections;
using System.Collections.Generic; // 新增用于List
using Logging;
using Managers; // 确保日志命名空间正确
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;
public Gradient progressBar; // 渐变色条
// 假设 CustomProgressBar 是一个自定义组件,其 API 与原代码使用方式一致
// 如果这里是 UnityEngine.UI.Image需要完全改变 Progress 和 Opacity 的实现
public Gradient progressBar; // 自定义进度条组件
public TMP_Text describeText; // 描述文本
public float duration = 0.5f; // 过渡时间
public float duration = 0.5f; // 每个步骤的过渡时间
public float fadeDuration = 2f; // 不透明度渐隐的时间
private float _currentProgress = 0f; // 当前进度
private Color textColor;
private float _currentProgressValue = 0f; // 实际的当前进度值0-1
private Color _initialTextColor; // 原始文本颜色,用于渐隐
private Color _initialProgressBarColor1; // 原始进度条颜色1
private Color _initialProgressBarColor2; // 原始进度条颜色2
private readonly string[] _loadingSteps =
{
"初始化日志", "正在载入定义", "正在加载图片资源", "正在切割瓦片", "正在加载区分派系",
"正在加载物品"
};
// 存储所有需要加载和清理的管理器
private List<ILaunchManager> _managersToLoad;
// Progress 属性,更新进度条和颜色
public float Progress
{
set
{
_currentProgress = value;
if (value < 0.5f)
{
progressBar.color2 = Color.Lerp(Color.black, Color.white, value * 2);
}
else
{
progressBar.color2 = Color.white;
progressBar.color1 = Color.Lerp(Color.black, Color.white, (value - 0.5f) * 2);
}
// 确保进度值在0到1之间提高健壮性
_currentProgressValue = Mathf.Clamp01(value);
progressBar.Refresh();
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 = (byte)(value * 255);
progressBar.color1.a = alpha;
progressBar.color2.a = alpha;
describeText.color = value > 0.5f ? Color.Lerp(new Color(1, 1, 1, 0), textColor, (value - 0.5f) * 2) : new Color(1, 1, 1, 0);
progressBar.Refresh();
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<ILaunchManager>
{
new Logging.LoggerManagerWrapper(), // 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
duration = Base.Setting.Instance.CurrentSettings.progressStepDuration;
fadeDuration = Base.Setting.Instance.CurrentSettings.exitAnimationDuration;
// 在非DEBUG模式下从设置中获取过渡时间
duration = Base.Setting.Instance.CurrentSettings.progressStepDuration;
fadeDuration = Base.Setting.Instance.CurrentSettings.exitAnimationDuration;
#endif
Load();
Program.Instance.needLoad = false;
Load(); // 启动加载流程内部会调用LoadAllManagers
Program.Instance.needLoad = false; // 加载完成后重置标志
}
/// <summary>
/// 启动游戏的加载流程。
/// </summary>
public void Load()
{
loadingUI.SetActive(true);
textColor = describeText.color;
loadingUI.SetActive(true); // 激活加载UI
Progress = 0f; // 重置进度
Opacity = 1f; // 重置透明度为完全不透明
StartCoroutine(LoadAllManagers());
}
/// <summary>
/// 清理所有管理器,然后重新加载。用于游戏重载或场景切换后需要重新初始化所有数据的情况。
/// </summary>
public void Reload()
{
Debug.Log("<color=yellow>Performing a full reload of all managers...</color>");
StopAllCoroutines(); // 停止当前所有正在运行的加载协程,避免冲突
ClearAllManagers(); // 清理所有管理器
Load(); // 重新加载游戏数据
}
/// <summary>
/// 遍历所有已注册的管理器并调用它们的 Clear 方法。
/// </summary>
private void ClearAllManagers()
{
foreach (var manager in _managersToLoad)
{
try
{
manager.Clear();
}
catch (System.Exception ex)
{
Debug.LogError($"<color=red>Error clearing manager {manager.StepDescription}:</color> {ex.Message}\n{ex.StackTrace}");
}
}
}
/// <summary>
/// 协程:按顺序加载所有管理器。
/// </summary>
private IEnumerator LoadAllManagers()
{
for (var i = 0; i < _loadingSteps.Length; i++)
for (var i = 0; i < _managersToLoad.Count; i++)
{
// 更新描述文本放在try外部
describeText.text = _loadingSteps[i];
var manager = _managersToLoad[i];
// 获取当前阶段的目标进度
var targetProgress = (float)(i + 1) / _loadingSteps.Length;
// 更新描述文本,从管理器实例中获取
if (describeText != null)
{
describeText.text = manager.StepDescription;
}
// 平滑过渡到下一个阶段放在try外部
// 计算当前阶段的目标进度
var targetProgress = (float)(i + 1) / _managersToLoad.Count;
// 平滑过渡进度条到下一个目标进度
yield return SmoothTransitionTo(targetProgress);
// 初始化对应的管理器(使用单独的方法处理可能抛出的异常)
yield return InitializeManagerSafely(i);
// 初始化对应的管理器,并进行异常处理
yield return InitializeManagerSafely(manager);
// 模拟耗时如果管理器Init方法本身很快可以 uncomment
// yield return new WaitForSeconds(0.1f);
}
// 加载完成后的处理
describeText.text = "加载完成!";
Progress = 1f;
// 所有管理器加载完成后的处理
if (describeText != null)
{
describeText.text = "加载完成!";
}
Progress = 1f; // 确保进度条最终达到100%
// 开始渐隐效果
yield return FadeOutProgressBar();
// 所有加载和动画结束后可以考虑卸载加载UI或跳转到主场景
// ToScene("MainGameScene"); // 如果有需要,在这里跳转到主游戏场景
}
private IEnumerator InitializeManagerSafely(int stepIndex)
/// <summary>
/// 尝试安全地初始化单个管理器,并捕获任何异常。
/// </summary>
/// <param name="manager">要初始化的管理器实例。</param>
private IEnumerator InitializeManagerSafely(ILaunchManager manager)
{
bool initSuccess = false;
var initSuccess = false;
System.Exception initException = null;
try
{
switch (stepIndex)
{
case 0:
UnityLogger.Init();
break;
case 1:
Managers.DefineManager.Instance.Init();
break;
case 2:
Managers.PackagesImageManager.Instance.Init();
break;
case 3:
Managers.TileManager.Instance.Init();
break;
case 4:
Managers.AffiliationManager.Instance.Init();
break;
case 5:
Managers.ItemResourceManager.Instance.Init();
break;
}
manager.Init(); // 调用管理器的 Init 方法
initSuccess = true;
}
catch (System.Exception ex)
{
initException = ex;
initException = ex; // 捕获异常
}
if (!initSuccess && initException != null)
{
Debug.LogError($"初始化第 {stepIndex + 1} 个管理器时出错: {initException.Message}\n{initException.StackTrace}");
describeText.text = $"{_loadingSteps[stepIndex]} (初始化失败)";
// 这里可以添加重试逻辑
// yield return RetryInitialize(stepIndex);
// 记录错误日志
Debug.LogError($"<color=red>初始化管理器 '{manager.StepDescription}' 时出错:</color> {initException.Message}\n{initException.StackTrace}");
if (describeText != null)
{
describeText.text = $"{manager.StepDescription} (初始化失败)";
}
// 这里可以添加更复杂的错误处理,例如显示错误弹窗,或者重试逻辑
// yield break; // 如果错误严重,可以选择停止后续加载
}
// 确保协程继续执行
yield return null;
yield return null; // 确保协程继续执行,即使没有做任何事
}
/// <summary>
/// 协程:平滑过渡进度条到指定的目标进度。
/// </summary>
/// <param name="targetProgress">目标进度值 (0-1)。</param>
private IEnumerator SmoothTransitionTo(float targetProgress)
{
var startProgress = _currentProgress;
var startProgress = _currentProgressValue; // 获取当前进度作为起始点
var elapsedTime = 0f;
while (elapsedTime < duration)
{
elapsedTime += Time.deltaTime;
var t = Mathf.SmoothStep(0f, 1f, elapsedTime / duration); // 使用 SmoothStep 实现平滑过渡
// 使用 SmoothStep 实现更自然的加速和减速过渡效果
var t = Mathf.SmoothStep(0f, 1f, elapsedTime / duration);
Progress = Mathf.Lerp(startProgress, targetProgress, t);
yield return null;
}
// 确保最终进度达到目标值
Progress = targetProgress;
Progress = targetProgress; // 确保最终进度精确达到目标值
}
/// <summary>
/// 协程渐隐加载UI的透明度。
/// </summary>
private IEnumerator FadeOutProgressBar()
{
var elapsedTime = 0f;
@ -173,19 +295,26 @@ namespace Base
while (elapsedTime < fadeDuration)
{
elapsedTime += Time.deltaTime;
var t = Mathf.SmoothStep(0f, 1f, elapsedTime / fadeDuration); // 使用 SmoothStep 实现平滑渐隐
Opacity = 1f - t; // 不透明度从 1 到 0
// 使用 SmoothStep 实现平滑渐隐
var t = Mathf.SmoothStep(0f, 1f, elapsedTime / fadeDuration);
Opacity = 1f - t; // 透明度从 1 线性渐变到 0
yield return null;
}
// 确保最终不透明度为 0
Opacity = 0f;
loadingUI.SetActive(false);
Opacity = 0f; // 确保最终不透明度为 0
loadingUI.SetActive(false); // 完全隐藏加载UI
}
/// <summary>
/// 静态方法:加载指定名称的场景。
/// </summary>
/// <param name="scene">要加载的场景名称。</param>
public static void ToScene(string scene)
{
SceneManager.LoadScene(scene);
}
}
}
}