yyl
2026-05-11 51b0f6ed9f4e1d3bb6f8144470b46908c7699a96
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
using UnityEngine;
using UnityEngine.UI;
using Cysharp.Threading.Tasks;
using System;
using System.Threading;
 
/// <summary>
/// 战斗加载界面,显示战斗资源加载进度。
/// 在战斗资源异步加载期间展示,加载完成后自动关闭。
/// </summary>
public class BattleLoadingWin : UIBase
{
    [SerializeField] private Slider m_ProgressSlider;
    [SerializeField] private Text m_ProgressText;
    [SerializeField] private Text m_TipText;
 
    private float _currentProgress;
    private float _targetProgress;
    private bool _isComplete;
 
    /// <summary>
    /// 创建 IProgress&lt;float&gt; 适配器,用于集成异步加载的进度回报。
    /// </summary>
    public IProgress<float> CreateProgressReporter()
    {
        return new BattleLoadingProgress(this);
    }
 
    protected override void InitComponent()
    {
        base.InitComponent();
        _currentProgress = 0f;
        _targetProgress = 0f;
        _isComplete = false;
    }
 
    protected override void OnPreOpen()
    {
        base.OnPreOpen();
        _currentProgress = 0f;
        _targetProgress = 0f;
        _isComplete = false;
        UpdateUI();
        RefreshTip();
    }
 
    /// <summary>
    /// 设置加载进度 (0.0 ~ 1.0)。
    /// </summary>
    public void SetProgress(float progress)
    {
        _targetProgress = Mathf.Clamp01(progress);
        if (_targetProgress >= 1f)
        {
            _isComplete = true;
        }
    }
 
    /// <summary>
    /// 直接设置进度并刷新 UI(无平滑过渡)。
    /// </summary>
    public void SetProgressDirectly(float progress)
    {
        _targetProgress = Mathf.Clamp01(progress);
        _currentProgress = _targetProgress;
        UpdateUI();
 
        if (_targetProgress >= 1f)
        {
            _isComplete = true;
        }
    }
 
    private void LateUpdate()
    {
        if (Mathf.Abs(_currentProgress - _targetProgress) > 0.001f)
        {
            _currentProgress = Mathf.Lerp(_currentProgress, _targetProgress, Time.deltaTime * 5f);
 
            // 接近目标时直接对齐,避免无限趋近
            if (Mathf.Abs(_currentProgress - _targetProgress) < 0.005f)
            {
                _currentProgress = _targetProgress;
            }
 
            UpdateUI();
        }
 
        if (_isComplete && _currentProgress >= 0.99f)
        {
            _currentProgress = 1f;
            UpdateUI();
            OnLoadComplete();
        }
    }
 
    private void UpdateUI()
    {
        if (m_ProgressSlider != null)
        {
            m_ProgressSlider.value = _currentProgress;
        }
 
        if (m_ProgressText != null)
        {
            m_ProgressText.text = $"{(int)(_currentProgress * 100)}%";
        }
    }
 
    private void RefreshTip()
    {
        if (m_TipText != null && GeneralDefine.loadingTips != null && GeneralDefine.loadingTips.Length > 0)
        {
            var randomIndex = UnityEngine.Random.Range(0, GeneralDefine.loadingTips.Length);
            m_TipText.text = Language.Get(GeneralDefine.loadingTips[randomIndex]);
        }
    }
 
    private void OnLoadComplete()
    {
        // 延迟关闭,让玩家看到 100% 状态
        CompleteAndCloseAsync().Forget();
    }
 
    private async UniTask CompleteAndCloseAsync()
    {
        await UniTask.Delay(300, cancellationToken: this.GetCancellationTokenOnDestroy());
 
        if (this != null)
        {
            UIManager.Instance.CloseWindow(this);
        }
    }
 
    /// <summary>
    /// 显示战斗加载界面并返回进度回报器。
    /// 用法: var progress = await BattleLoadingWin.ShowAsync();
    /// </summary>
    public static async UniTask<BattleLoadingWin> ShowAsync()
    {
        var win = await UIManager.Instance.OpenWindowAsync("BattleLoadingWin") as BattleLoadingWin;
        return win;
    }
 
    /// <summary>
    /// IProgress 适配器实现。
    /// </summary>
    private class BattleLoadingProgress : IProgress<float>
    {
        private readonly BattleLoadingWin _win;
 
        public BattleLoadingProgress(BattleLoadingWin win)
        {
            _win = win;
        }
 
        public void Report(float value)
        {
            if (_win != null)
            {
                _win.SetProgress(value);
            }
        }
    }
}