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();
|
}
|
}
|