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