mirror of
http://47.107.252.169:3000/Roguelite-Game-Developing-Team/Gen_Hack-and-Slash-Roguelite.git
synced 2025-11-20 06:57:12 +08:00
(client) feat:健康给予,路径优化,结算界面,商店界面 (#60)
Co-authored-by: m0_75251201 <m0_75251201@noreply.gitcode.com> Reviewed-on: http://47.107.252.169:3000/Roguelite-Game-Developing-Team/Gen_Hack-and-Slash-Roguelite/pulls/60
This commit is contained in:
@@ -1,66 +1,79 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Configs; // 提供List等通用集合类型
|
||||
using Logging; // 提供日志记录功能
|
||||
using Managers; // 提供管理器接口和实现
|
||||
using System.Threading.Tasks; // 引入Task命名空间
|
||||
using Configs;
|
||||
using Logging;
|
||||
using Managers;
|
||||
using TMPro;
|
||||
using UI; // TextMeshPro文本组件命名空间
|
||||
using UnityEngine; // Unity引擎核心命名空间
|
||||
using UnityEngine.SceneManagement; // 场景管理命名空间
|
||||
using UI;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
// 提供List等通用集合类型
|
||||
// 提供日志记录功能
|
||||
// 提供管理器接口和实现
|
||||
// TextMeshPro文本组件命名空间
|
||||
// Unity引擎核心命名空间
|
||||
|
||||
// 场景管理命名空间
|
||||
|
||||
namespace Base
|
||||
{
|
||||
/// <summary>
|
||||
/// <c>Launcher</c> 类负责管理游戏的初始化加载流程,包括管理器加载、进度条显示和场景切换。
|
||||
/// <c>Launcher</c> 类负责管理游戏的初始化加载流程,包括管理器加载、进度条显示和场景切换。
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>请注意:虽然此处的 <c>progressBar</c> 变量类型被声明为 <c>Gradient</c>,
|
||||
/// 但其在代码中的使用方式(如访问 <c>color1</c>, <c>color2</c> 属性和调用 <c>Refresh()</c> 方法)
|
||||
/// 强烈暗示它应引用一个具有类似 API 的自定义进度条组件,例如 <c>CustomProgressBar</c>。</para>
|
||||
/// <para>如果您使用的是标准 <c>UnityEngine.UI.Image</c> 或其他组件来显示进度,
|
||||
/// 则 <c>Progress</c> 和 <c>Opacity</c> 属性的实现逻辑需要根据实际组件的 API 进行大幅修改。</para>
|
||||
/// <para>
|
||||
/// 请注意:虽然此处的 <c>progressBar</c> 变量类型被声明为 <c>Gradient</c>,
|
||||
/// 但其在代码中的使用方式(如访问 <c>color1</c>, <c>color2</c> 属性和调用 <c>Refresh()</c> 方法)
|
||||
/// 强烈暗示它应引用一个具有类似 API 的自定义进度条组件,例如 <c>CustomProgressBar</c>。
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// 如果您使用的是标准 <c>UnityEngine.UI.Image</c> 或其他组件来显示进度,
|
||||
/// 则 <c>Progress</c> 和 <c>Opacity</c> 属性的实现逻辑需要根据实际组件的 API 进行大幅修改。
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public class Launcher : MonoBehaviour
|
||||
{
|
||||
/// <summary>
|
||||
/// 加载界面UI的根游戏对象。
|
||||
/// 加载界面UI的根游戏对象。
|
||||
/// </summary>
|
||||
public GameObject loadingUI;
|
||||
|
||||
/// <summary>
|
||||
/// 用于显示加载进度的自定义进度条组件。
|
||||
/// <para>请参阅类注释以了解其声明类型与预期API的差异。</para>
|
||||
/// 用于显示加载进度的自定义进度条组件。
|
||||
/// <para>请参阅类注释以了解其声明类型与预期API的差异。</para>
|
||||
/// </summary>
|
||||
public ColorBar progressBar;
|
||||
|
||||
/// <summary>
|
||||
/// 用于显示当前加载步骤描述的文本组件。
|
||||
/// 用于显示当前加载步骤描述的文本组件。
|
||||
/// </summary>
|
||||
public TMP_Text describeText;
|
||||
|
||||
/// <summary>
|
||||
/// 进度条每个加载步骤的平滑过渡时间(秒)。
|
||||
/// 进度条每个加载步骤的平滑过渡时间(秒)。
|
||||
/// </summary>
|
||||
public float duration = 0.5f;
|
||||
|
||||
/// <summary>
|
||||
/// 加载完成后UI元素渐隐的时间(秒)。
|
||||
/// 加载完成后UI元素渐隐的时间(秒)。
|
||||
/// </summary>
|
||||
public float fadeDuration = 2f;
|
||||
|
||||
private float _currentProgressValue = 0f; // 实际的当前进度值(在0到1之间)
|
||||
private Color _initialTextColor; // 描述文本的原始颜色,用于渐隐效果
|
||||
private float _currentProgressValue; // 实际的当前进度值(在0到1之间)
|
||||
private Color _initialProgressBarColor1; // 进度条颜色1的原始值,用于渐变
|
||||
private Color _initialProgressBarColor2; // 进度条颜色2的原始值,用于渐变
|
||||
private Color _initialTextColor; // 描述文本的原始颜色,用于渐隐效果
|
||||
|
||||
/// <summary>
|
||||
/// 存储所有需要在启动时加载和在重载时清理的管理器实例列表。
|
||||
/// 存储所有需要在启动时加载和在重载时清理的管理器实例列表。
|
||||
/// </summary>
|
||||
private List<ILaunchManager> _managersToLoad;
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置加载进度值,范围为0到1。
|
||||
/// 设置此属性将更新进度条的视觉显示和颜色。
|
||||
/// 获取或设置加载进度值,范围为0到1。
|
||||
/// 设置此属性将更新进度条的视觉显示和颜色。
|
||||
/// </summary>
|
||||
public float Progress
|
||||
{
|
||||
@@ -69,20 +82,23 @@ namespace Base
|
||||
// 确保进度值在0到1之间,提高系统健壮性
|
||||
_currentProgressValue = Mathf.Clamp01(value);
|
||||
|
||||
if (progressBar)
|
||||
if (progressBar != null) // 对外部引用的组件进行空检查是必要的
|
||||
{
|
||||
// 根据进度值平滑改变进度条的颜色
|
||||
if (_currentProgressValue < 0.5f)
|
||||
{
|
||||
// 前半段:color2 从初始色渐变到白色
|
||||
progressBar.color2 = Color.Lerp(_initialProgressBarColor2, Color.white, _currentProgressValue * 2);
|
||||
progressBar.color2 = Color.Lerp(_initialProgressBarColor2, Color.white,
|
||||
_currentProgressValue * 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
progressBar.color2 = Color.white;
|
||||
// 后半段:color2 保持白色,color1 从初始色渐变到白色
|
||||
progressBar.color1 = Color.Lerp(_initialProgressBarColor1, Color.white, (_currentProgressValue - 0.5f) * 2);
|
||||
progressBar.color1 = Color.Lerp(_initialProgressBarColor1, Color.white,
|
||||
(_currentProgressValue - 0.5f) * 2);
|
||||
}
|
||||
|
||||
// 通知自定义进度条组件更新显示。
|
||||
// 注意:UnityEngine.Gradient 作为数据结构没有 Refresh() 方法,
|
||||
// 此调用表明 progressBar 实际上预期是一个具有此方法的自定义组件。
|
||||
@@ -93,8 +109,8 @@ namespace Base
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置UI元素的整体不透明度,范围0(完全透明)到1(完全不透明)。
|
||||
/// 设置此属性将更新进度条和描述文本的透明度。
|
||||
/// 获取或设置UI元素的整体不透明度,范围0(完全透明)到1(完全不透明)。
|
||||
/// 设置此属性将更新进度条和描述文本的透明度。
|
||||
/// </summary>
|
||||
public float Opacity
|
||||
{
|
||||
@@ -102,7 +118,7 @@ namespace Base
|
||||
{
|
||||
var alpha = Mathf.Clamp01(value); // 确保透明度值在0到1之间
|
||||
|
||||
if (progressBar)
|
||||
if (progressBar != null) // 对外部引用的组件进行空检查是必要的
|
||||
{
|
||||
// 更新进度条颜色的透明度
|
||||
Color c1 = progressBar.color1;
|
||||
@@ -119,19 +135,20 @@ namespace Base
|
||||
progressBar.Refresh();
|
||||
}
|
||||
|
||||
if (describeText)
|
||||
if (describeText != null) // 对外部引用的组件进行空检查是必要的
|
||||
{
|
||||
// 更新描述文本颜色的透明度
|
||||
// 渐隐时,描述文本的透明度在 Opacity > 0.5f 时才开始从0渐变到其原始透明度
|
||||
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);
|
||||
describeText.color = new Color(_initialTextColor.r, _initialTextColor.g, _initialTextColor.b,
|
||||
textAlpha);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 当脚本实例被启用时调用一次。
|
||||
/// 用于初始化管理器列表并缓存UI元素的初始颜色。
|
||||
/// 当脚本实例被启用时调用一次。
|
||||
/// 用于初始化管理器列表并缓存UI元素的初始颜色。
|
||||
/// </summary>
|
||||
private void Awake()
|
||||
{
|
||||
@@ -148,15 +165,18 @@ namespace Base
|
||||
EventManager.Instance,
|
||||
AudioManager.Instance,
|
||||
SkillTreeManager.Instance,
|
||||
|
||||
|
||||
KeyValueArchiveManager.Instance,
|
||||
SaveManager.Instance, // 存档管理器应在其他依赖管理器之后加载
|
||||
|
||||
HediffManager.Instance
|
||||
};
|
||||
|
||||
// 缓存UI的初始颜色,以便后续操作(如渐隐)或重置
|
||||
_initialTextColor = describeText != null ? describeText.color : Color.white; // 如果为空,则使用默认值
|
||||
|
||||
if (progressBar != null)
|
||||
// 对UnityEngine.Object的组件进行空检查是必要的
|
||||
_initialTextColor = (describeText != null) ? describeText.color : Color.white;
|
||||
|
||||
if (progressBar != null) // 对UnityEngine.Object的组件进行空检查是必要的
|
||||
{
|
||||
_initialProgressBarColor1 = progressBar.color1;
|
||||
_initialProgressBarColor2 = progressBar.color2;
|
||||
@@ -169,12 +189,13 @@ namespace Base
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在Awake方法之后、首次帧更新之前调用。
|
||||
/// 用于判断是否需要执行完整的加载流程,并根据需要启动加载或隐藏加载UI。
|
||||
/// 在Awake方法之后、首次帧更新之前调用。
|
||||
/// 用于判断是否需要执行完整的加载流程,并根据需要启动加载或隐藏加载UI。
|
||||
/// </summary>
|
||||
private void Start()
|
||||
{
|
||||
// 如果 Program.Instance.needLoad 为 false,表示游戏已加载或不需要重新加载,直接隐藏加载UI
|
||||
// Program.Instance 假设是一个单例,不进行空检查
|
||||
// Program.Instance.NeedLoad 为 false,表示游戏已加载或不需要重新加载,直接隐藏加载UI
|
||||
if (!Program.Instance.NeedLoad)
|
||||
{
|
||||
loadingUI.SetActive(false);
|
||||
@@ -184,21 +205,21 @@ namespace Base
|
||||
// 如果需要加载,则先清理所有管理器(用于重载或确保干净启动),再启动加载流程
|
||||
ClearAllManagers();
|
||||
|
||||
// 初始化游戏设置
|
||||
// 初始化游戏设置 (Setting.Instance 假设是一个单例,不进行空检查)
|
||||
Setting.Instance.Init();
|
||||
|
||||
#if !DEBUG
|
||||
// 在非DEBUG模式下,从游戏设置中获取加载和渐隐的持续时间
|
||||
duration = Base.Setting.Instance.CurrentSettings.progressStepDuration;
|
||||
fadeDuration = Base.Setting.Instance.CurrentSettings.exitAnimationDuration;
|
||||
// 在非DEBUG模式下,从游戏设置中获取加载和渐隐的持续时间 (Setting.Instance 假设是一个单例,不进行空检查)
|
||||
duration = Setting.Instance.CurrentSettings.progressStepDuration;
|
||||
fadeDuration = Setting.Instance.CurrentSettings.exitAnimationDuration;
|
||||
#endif
|
||||
Load(); // 启动加载流程(内部会调用LoadAllManagers)
|
||||
Program.Instance.NeedLoad = false; // 加载完成后重置加载标志
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 启动游戏的加载流程。
|
||||
/// 该方法会激活加载UI,重置进度与透明度,并启动所有管理器的异步加载协程。
|
||||
/// 启动游戏的加载流程。
|
||||
/// 该方法会激活加载UI,重置进度与透明度,并启动所有管理器的异步加载协程。
|
||||
/// </summary>
|
||||
public void Load()
|
||||
{
|
||||
@@ -209,8 +230,8 @@ namespace Base
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清理所有管理器,然后重新加载游戏数据。
|
||||
/// 此方法适用于游戏重载、场景切换后需要重新初始化所有数据的情况。
|
||||
/// 清理所有管理器,然后重新加载游戏数据。
|
||||
/// 此方法适用于游戏重载、场景切换后需要重新初始化所有数据的情况。
|
||||
/// </summary>
|
||||
public void Reload()
|
||||
{
|
||||
@@ -222,29 +243,29 @@ namespace Base
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 遍历所有已注册的管理器,并安全地调用它们的 Clear 方法以释放资源或重置状态。
|
||||
/// 遍历所有已注册的管理器,并安全地调用它们的 Clear 方法以释放资源或重置状态。
|
||||
/// </summary>
|
||||
private void ClearAllManagers()
|
||||
{
|
||||
foreach (var manager in _managersToLoad)
|
||||
{
|
||||
try
|
||||
{
|
||||
manager.Clear();
|
||||
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
catch (Exception ex)
|
||||
{
|
||||
// 错误日志:清理管理器时发生异常。
|
||||
Debug.LogError($"<color=red>清理管理器 '{manager.StepDescription}' 时出错:</color> {ex.Message}\n{ex.StackTrace}");
|
||||
Debug.LogError(
|
||||
$"<color=red>清理管理器 '{manager.StepDescription}' 时出错:</color> {ex.Message}\n{ex.StackTrace}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 协程:按顺序加载所有注册的管理器。
|
||||
/// 该方法会在加载过程中更新描述文本、平滑过渡进度条,并安全初始化每个管理器。
|
||||
/// 协程:按顺序加载所有注册的管理器。
|
||||
/// 该方法会在加载过程中更新描述文本、平滑过渡进度条,并安全初始化每个管理器。
|
||||
/// </summary>
|
||||
/// <returns>一个 <see cref="IEnumerator"/>,用于协程。</returns>
|
||||
/// <returns>一个 <see cref="IEnumerator" />,用于协程。</returns>
|
||||
private IEnumerator LoadAllManagers()
|
||||
{
|
||||
for (var i = 0; i < _managersToLoad.Count; i++)
|
||||
@@ -252,10 +273,9 @@ namespace Base
|
||||
var manager = _managersToLoad[i];
|
||||
|
||||
// 更新描述文本,显示当前正在加载的管理器步骤描述
|
||||
if (describeText != null)
|
||||
{
|
||||
// 对TMP_Text组件进行空检查是必要的
|
||||
if (describeText)
|
||||
describeText.text = manager.StepDescription;
|
||||
}
|
||||
|
||||
// 计算当前阶段的目标进度值
|
||||
var targetProgress = (float)(i + 1) / _managersToLoad.Count;
|
||||
@@ -264,16 +284,15 @@ namespace Base
|
||||
yield return SmoothTransitionTo(targetProgress);
|
||||
|
||||
// 初始化对应的管理器,并处理可能发生的异常
|
||||
// InitializeManagerSafely现在内部会等待异步任务完成
|
||||
yield return InitializeManagerSafely(manager);
|
||||
|
||||
|
||||
// yield return new WaitForSeconds(0.1f); // 此行代码可用于模拟每个管理器加载的耗时,默认不启用。
|
||||
}
|
||||
|
||||
// 所有管理器加载完成后的处理
|
||||
if (describeText != null)
|
||||
{
|
||||
if (describeText != null) // 对TMP_Text组件进行空检查是必要的
|
||||
describeText.text = "加载完成!";
|
||||
}
|
||||
// 确保进度条最终达到100%
|
||||
Progress = 1f;
|
||||
|
||||
@@ -285,47 +304,48 @@ namespace Base
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 尝试安全地初始化单个管理器实例,并捕获任何可能发生的异常。
|
||||
/// 如果初始化失败,将记录错误日志并更新UI提示。
|
||||
/// 尝试安全地初始化单个管理器实例,并捕获任何可能发生的异常。
|
||||
/// 如果初始化失败,将记录错误日志并更新UI提示。
|
||||
/// </summary>
|
||||
/// <param name="manager">要初始化的管理器实例。</param>
|
||||
/// <returns>一个 <see cref="IEnumerator"/>,用于协程。</returns>
|
||||
/// <returns>一个 <see cref="IEnumerator" />,用于协程。</returns>
|
||||
private IEnumerator InitializeManagerSafely(ILaunchManager manager)
|
||||
{
|
||||
var initSuccess = false;
|
||||
System.Exception initException = null;
|
||||
// 启动异步初始化任务,不再直接同步调用
|
||||
var initTask = manager.Init();
|
||||
|
||||
try
|
||||
// 持续等待,直到任务完成 (非阻塞式等待)
|
||||
while (!initTask.IsCompleted)
|
||||
{
|
||||
manager.Init(); // 调用管理器的 Init 方法进行初始化
|
||||
initSuccess = true;
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
initException = ex; // 捕获初始化过程中抛出的异常
|
||||
yield return null; // 等待下一帧
|
||||
}
|
||||
|
||||
if (!initSuccess && initException != null)
|
||||
// 检查任务是否因异常而失败
|
||||
if (initTask.IsFaulted)
|
||||
{
|
||||
// 记录错误日志:初始化管理器时出现错误。
|
||||
Debug.LogError($"<color=red>初始化管理器 '{manager.StepDescription}' 时出错:</color> {initException.Message}\n{initException.StackTrace}");
|
||||
if (describeText != null)
|
||||
{
|
||||
describeText.text = $"{manager.StepDescription} (初始化失败)"; // 更新UI显示失败信息
|
||||
}
|
||||
// 这里可以添加更复杂的错误处理逻辑,例如显示错误弹窗、记录到特定日志文件或允许用户选择重试。
|
||||
// yield break; // 如果错误严重到无法继续,可以选择停止后续加载流程。
|
||||
// 提取任务链中的实际异常信息,AggregateException可能包含多个内部异常
|
||||
// 使用 ?? 运算符确保即使 InnerException 为 null 也能获取到异常信息
|
||||
var initException = initTask.Exception.InnerException ?? initTask.Exception;
|
||||
Debug.LogError(
|
||||
$"<color=red>初始化管理器 '{manager.StepDescription}' 时出错: {initException.Message}\n{initException.StackTrace}</color>");
|
||||
if (describeText) // 对UnityEngine.Object的组件进行空检查是必要的
|
||||
describeText.text = $"{manager.StepDescription} (初始化失败)";
|
||||
}
|
||||
|
||||
yield return null; // 确保协程继续执行,无论初始化成功与否
|
||||
else if (initTask.IsCanceled) // 额外增加对取消状态的处理
|
||||
{
|
||||
Debug.LogWarning($"<color=orange>初始化管理器 '{manager.StepDescription}' 被取消。</color>");
|
||||
if (describeText) // 对UnityEngine.Object的组件进行空检查是必要的
|
||||
describeText.text = $"{manager.StepDescription} (已取消)";
|
||||
}
|
||||
// 协程会自然结束,不再需要额外的 yield return null
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 协程:平滑地过渡进度条的当前值到指定的目标进度。
|
||||
/// 使用 <c>Mathf.SmoothStep</c> 实现自然加速和减速的过渡效果。
|
||||
/// 协程:平滑地过渡进度条的当前值到指定的目标进度。
|
||||
/// 使用 <c>Mathf.SmoothStep</c> 实现自然加速和减速的过渡效果。
|
||||
/// </summary>
|
||||
/// <param name="targetProgress">目标进度值 (0到1之间)。</param>
|
||||
/// <returns>一个 <see cref="IEnumerator"/>,用于协程。</returns>
|
||||
/// <returns>一个 <see cref="IEnumerator" />,用于协程。</returns>
|
||||
private IEnumerator SmoothTransitionTo(float targetProgress)
|
||||
{
|
||||
var startProgress = _currentProgressValue; // 获取当前进度作为过渡的起始点
|
||||
@@ -344,9 +364,9 @@ namespace Base
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 协程:平滑渐隐加载UI的所有元素,使其透明度从完全不透明过渡到完全透明。
|
||||
/// 协程:平滑渐隐加载UI的所有元素,使其透明度从完全不透明过渡到完全透明。
|
||||
/// </summary>
|
||||
/// <returns>一个 <see cref="IEnumerator"/>,用于协程。</returns>
|
||||
/// <returns>一个 <see cref="IEnumerator" />,用于协程。</returns>
|
||||
private IEnumerator FadeOutProgressBar()
|
||||
{
|
||||
var elapsedTime = 0f;
|
||||
@@ -365,7 +385,7 @@ namespace Base
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 静态方法:加载指定名称的Unity场景。
|
||||
/// 静态方法:加载指定名称的Unity场景。
|
||||
/// </summary>
|
||||
/// <param name="scene">要加载的场景名称。</param>
|
||||
public static void ToScene(string scene)
|
||||
|
||||
Reference in New Issue
Block a user