using System; using System.Collections; using System.Collections.Generic; using System.Linq; using FairyGUI; using RedHotRoast; using UnityEngine; using UnityEngine.Video; internal class VideoLoadTask { public Coroutine coroutine; public string fileName; public bool isCancelled; public GLoader loader; public Action onComplete; public bool play; public VideoPlayer player; // loader 绑定的任务 ID public string taskId; } internal class VideoLoadScheduler { private const int MaxConcurrent = 1; // 同时加载任务数 private static readonly Queue taskQueue = new(); private static readonly List runningTasks = new(); /// /// 入队视频加载任务 /// public static void EnqueueLoad(VideoPlayer player, string fileName, GLoader loader, Action onComplete, bool play = true) { // 🔑 检查重复任务 var 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(); } /// /// 尝试启动队列中的任务 /// 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); } } /// /// 协程加载视频 /// 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(); } } /// /// 取消某个任务 /// 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(); } /// /// 清理所有任务 /// public static void ClearAll() { // 倒序遍历,避免索引错乱 for (int i = runningTasks.Count - 1; i >= 0; i--) { CancelTask(runningTasks[i]); } taskQueue.Clear(); runningTasks.Clear(); Debug.Log("[VideoScheduler] 所有任务已清理"); } } /// /// 扩展方法:GLoader 绑定当前任务 ID /// public static class GLoaderExtensions { private static readonly Dictionary 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; } }