Files
2026-04-20 12:06:34 +08:00

183 lines
5.6 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using BallKingdomCrush;
using FairyGUI;
using UnityEngine;
using UnityEngine.Video;
internal class VideoLoadTask
{
public Coroutine coroutine;
public string fileName;
public bool isCancelled;
public GLoader loader;
public Action<VideoPlayer> onComplete;
public bool play;
public VideoPlayer player;
// loader 绑定的任务 ID
public string taskId;
}
internal class VideoLoadScheduler
{
private const int MaxConcurrent = 6; // 同时加载任务数
private static readonly Queue<VideoLoadTask> taskQueue = new();
private static readonly List<VideoLoadTask> runningTasks = new();
/// <summary>
/// 入队视频加载任务
/// </summary>
public static void EnqueueLoad(VideoPlayer player, string fileName, GLoader loader, Action<VideoPlayer> onComplete, bool play = true)
{
// 🔑 检查重复任务
bool isDuplicate = taskQueue.Any(t => t.fileName == fileName && t.loader == loader && !t.isCancelled);
if (isDuplicate)
{
Debug.LogWarning($"[VideoScheduler] 跳过重复任务: {fileName}, loader={loader.name}");
return;
}
// 生成唯一 taskId,绑定到 loader
var taskId = Guid.NewGuid().ToString();
loader.SetData(taskId);
var task = new VideoLoadTask
{
fileName = fileName,
loader = loader,
onComplete = onComplete,
play = play,
player = player,
taskId = taskId
};
taskQueue.Enqueue(task);
Debug.Log($"[VideoScheduler] 入队视频: {fileName}, taskId={taskId}, queueCount={taskQueue.Count}");
TryStartNext();
}
/// <summary>
/// 尝试启动队列中的任务
/// </summary>
private static void TryStartNext()
{
Debug.Log($"[VideoScheduler] TryStartNext 调用,queue={taskQueue.Count}, running={runningTasks.Count}");
while (taskQueue.Count > 0 && runningTasks.Count < MaxConcurrent)
{
var task = taskQueue.Dequeue();
if (task.isCancelled)
{
Debug.Log($"[VideoScheduler] 跳过已取消任务: {task.fileName}, taskId={task.taskId}");
continue;
}
Debug.Log($"[VideoScheduler] 启动任务: {task.fileName}, taskId={task.taskId}");
var co = CrazyAsyKit.StartCoroutine(LoadVideoToPlayer(task.player, task));
task.coroutine = co;
runningTasks.Add(task);
}
}
/// <summary>
/// 协程加载视频
/// </summary>
private static IEnumerator LoadVideoToPlayer(VideoPlayer player, VideoLoadTask task)
{
Debug.Log($"[VideoScheduler] 开始加载视频: {task.fileName}, taskId={task.taskId}");
var callbackTriggered = false;
yield return LiveVideoManager.LoadVideoToPlayer(player, task.fileName, task.loader, vp =>
{
callbackTriggered = true;
Debug.Log(
$"[VideoScheduler] 回调触发: {task.fileName}, loader taskId={task.loader.GetData()}, current taskId={task.taskId}");
if (task.loader.GetData() != task.taskId)
{
Debug.Log($"[VideoScheduler] 任务被覆盖,丢弃: {task.fileName}, taskId={task.taskId}");
}
else if (task.isCancelled)
{
Debug.Log($"[VideoScheduler] 任务被取消: {task.fileName}, taskId={task.taskId}");
if (vp != null) vp.Stop();
task.onComplete?.Invoke(null);
}
else
{
Debug.Log($"[VideoScheduler] 任务完成: {task.fileName}, taskId={task.taskId}");
task.onComplete?.Invoke(vp);
}
runningTasks.Remove(task);
Debug.Log($"[VideoScheduler] 移除任务,剩余: {runningTasks.Count}");
TryStartNext();
}, task.play);
// 🔴 兜底:防止 TextureHelper 出错导致回调不触发
if (!callbackTriggered)
{
Debug.LogWarning($"[VideoScheduler] ⚠️ 没有回调就结束了,强制移除任务: {task.fileName}, taskId={task.taskId}");
runningTasks.Remove(task);
TryStartNext();
}
}
/// <summary>
/// 取消某个任务
/// </summary>
public static void CancelTask(VideoLoadTask task)
{
if (task == null) return;
task.isCancelled = true;
if (task.coroutine != null)
CrazyAsyKit.StopCoroutine(task.coroutine);
if (runningTasks.Remove(task))
Debug.Log($"[VideoScheduler] 取消并移除任务: {task.fileName}, taskId={task.taskId}");
TryStartNext();
}
/// <summary>
/// 清理所有任务
/// </summary>
public static void ClearAll()
{
foreach (var task in runningTasks)
CancelTask(task);
taskQueue.Clear();
runningTasks.Clear();
Debug.Log("[VideoScheduler] 所有任务已清理");
}
}
/// <summary>
/// 扩展方法:GLoader 绑定当前任务 ID
/// </summary>
public static class GLoaderExtensions
{
private static readonly Dictionary<GLoader, string> loaderTaskMap = new();
public static void SetData(this GLoader loader, string taskId)
{
loaderTaskMap[loader] = taskId;
}
public static string GetData(this GLoader loader)
{
if (loaderTaskMap.TryGetValue(loader, out var taskId))
return taskId;
return null;
}
}