yyl
2026-02-11 1ad03cc2f91d75e80fc3dc42e2ac1fadc9a2bfec
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
using System;
using System.Collections.Generic;
using UnityEngine;
using Cysharp.Threading.Tasks;
 
/// <summary>
/// US3: 异步资源守卫,延迟特效/Spine播放直到资源就绪。
/// 在资源未加载完成时排队播放请求,加载完成后按顺序执行。
/// </summary>
public class AsyncResourceGuard
{
    private bool _isReady;
    private readonly Queue<Action> _pendingActions = new Queue<Action>();
    private UniTaskCompletionSource _readySource;
 
    public bool IsReady => _isReady;
 
    public AsyncResourceGuard()
    {
        _isReady = false;
        _readySource = new UniTaskCompletionSource();
    }
 
    /// <summary>
    /// 标记资源已就绪,执行所有排队的动作。
    /// </summary>
    public void SetReady()
    {
        if (_isReady) return;
 
        _isReady = true;
        _readySource.TrySetResult();
 
        // 执行所有排队的动作
        while (_pendingActions.Count > 0)
        {
            var action = _pendingActions.Dequeue();
            try
            {
                action?.Invoke();
            }
            catch (Exception e)
            {
                Debug.LogException(e);
            }
        }
    }
 
    /// <summary>
    /// 排队一个动作:如果资源已就绪则立即执行,否则排队等待。
    /// </summary>
    public void EnqueueOrExecute(Action action)
    {
        if (action == null) return;
 
        if (_isReady)
        {
            action.Invoke();
        }
        else
        {
            _pendingActions.Enqueue(action);
        }
    }
 
    /// <summary>
    /// 等待资源就绪(可用于 await)。
    /// </summary>
    public UniTask WaitUntilReady()
    {
        if (_isReady) return UniTask.CompletedTask;
        return _readySource.Task;
    }
 
    /// <summary>
    /// 重置状态,用于资源重新加载。
    /// </summary>
    public void Reset()
    {
        _isReady = false;
        _pendingActions.Clear();
        _readySource = new UniTaskCompletionSource();
    }
 
    /// <summary>
    /// 清空所有排队的动作(如场景切换时)。
    /// </summary>
    public void ClearPending()
    {
        _pendingActions.Clear();
    }
}
 
/// <summary>
/// US3: MonoBehaviour 版异步资源守卫,可挂载到需要等待资源的 GameObject 上。
/// 典型用法:在 BattleField 上管理特效/Spine 的延迟播放。
/// </summary>
public class AsyncResourceGuardBehaviour : MonoBehaviour
{
    private readonly AsyncResourceGuard _guard = new AsyncResourceGuard();
 
    public bool IsReady => _guard.IsReady;
 
    /// <summary>
    /// 标记资源就绪,触发所有排队播放。
    /// </summary>
    public void SetReady()
    {
        _guard.SetReady();
    }
 
    /// <summary>
    /// 提交一个播放请求:资源就绪则立即执行,否则排队。
    /// </summary>
    public void Play(Action playAction)
    {
        if (this == null) return;
        _guard.EnqueueOrExecute(playAction);
    }
 
    /// <summary>
    /// 等待资源就绪。
    /// </summary>
    public UniTask WaitUntilReady()
    {
        return _guard.WaitUntilReady();
    }
 
    /// <summary>
    /// 重置守卫状态。
    /// </summary>
    public void ResetGuard()
    {
        _guard.Reset();
    }
 
    private void OnDestroy()
    {
        _guard.ClearPending();
    }
}