diff --git a/Assets/TcgEngine/Prefabs/UI/Task/TaskItem.prefab b/Assets/TcgEngine/Prefabs/UI/Task/TaskItem.prefab index f0d1fe0..4b16b6a 100644 --- a/Assets/TcgEngine/Prefabs/UI/Task/TaskItem.prefab +++ b/Assets/TcgEngine/Prefabs/UI/Task/TaskItem.prefab @@ -1,5 +1,81 @@ %YAML 1.1 %TAG !u! tag:unity3d.com,2011: +--- !u!1 &289357591702079950 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 284419844733056354} + - component: {fileID: 2327016636593761779} + - component: {fileID: 6541735992704929191} + m_Layer: 5 + m_Name: TaskEnd + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &284419844733056354 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 289357591702079950} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 5317638608411323970} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 1} + m_AnchorMax: {x: 0.5, y: 1} + m_AnchoredPosition: {x: 0, y: -103.5} + m_SizeDelta: {x: 208, y: 207} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &2327016636593761779 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 289357591702079950} + m_CullTransparentMesh: 1 +--- !u!114 &6541735992704929191 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 289357591702079950} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0, g: 0, b: 0, a: 0.5019608} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 21300000, guid: 9ab53655a84d45141aa067f5b6fb2052, type: 3} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 --- !u!1 &327409933916102576 GameObject: m_ObjectHideFlags: 0 @@ -815,6 +891,7 @@ GameObject: - component: {fileID: 5317638608411323970} - component: {fileID: 5317638608411323968} - component: {fileID: 630132774} + - component: {fileID: 5368359024977481613} m_Layer: 5 m_Name: TaskItem m_TagString: Untagged @@ -837,6 +914,7 @@ RectTransform: - {fileID: 7062832204315600226} - {fileID: 5317638608209919160} - {fileID: 7416038335489522091} + - {fileID: 284419844733056354} m_Father: {fileID: 0} m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} @@ -865,6 +943,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: c56a7ede4255693469095ed5b8242daf, type: 3} m_Name: m_EditorClassIdentifier: + display_speed: 4 taskID: taskName_text: {fileID: 5317638608209919161} teskDesc_text: {fileID: 5317638606691184680} @@ -872,6 +951,19 @@ MonoBehaviour: progressBar_text: {fileID: 5317638606810153107} reward_button: {fileID: 4730874702436785540} reward_icon: {fileID: 5317638608707530455} + taskEnd_img: {fileID: 6541735992704929191} +--- !u!225 &5368359024977481613 +CanvasGroup: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5317638608411323973} + m_Enabled: 1 + m_Alpha: 1 + m_Interactable: 1 + m_BlocksRaycasts: 1 + m_IgnoreParentGroups: 0 --- !u!1 &5317638608707530441 GameObject: m_ObjectHideFlags: 0 @@ -988,7 +1080,7 @@ MonoBehaviour: m_PressedTrigger: Pressed m_SelectedTrigger: Selected m_DisabledTrigger: Disabled - m_Interactable: 1 + m_Interactable: 0 m_TargetGraphic: {fileID: 5317638608707530455} m_OnClick: m_PersistentCalls: diff --git a/Assets/TcgEngine/Scripts/GameClient/GameClientTaskIntegration.cs b/Assets/TcgEngine/Scripts/GameClient/GameClientTaskIntegration.cs index da3b43f..a3178b7 100644 --- a/Assets/TcgEngine/Scripts/GameClient/GameClientTaskIntegration.cs +++ b/Assets/TcgEngine/Scripts/GameClient/GameClientTaskIntegration.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using UnityEngine; using TcgEngine.Gameplay; using TcgEngine.UI; +using System.Linq; namespace TcgEngine.Client { @@ -46,7 +47,10 @@ namespace TcgEngine.Client // 找 UI 面板 taskPanel = GetComponent(); if (taskPanel == null) + { taskPanel = FindObjectOfType(); + } + } private void OnDestroy() @@ -62,13 +66,13 @@ namespace TcgEngine.Client if (taskManager != null) { taskManager.OnPlayerLogin(); - taskPanel.ShowTasks(taskManager.GetAllTasks()); + // 强制第一次刷新 + OnRefreshTaskPanel(TaskManager.Instance.GetAllTasks()); } } private void OnRefreshTaskPanel(List tasksList) { - TaskManager taskManager = TaskManager.Instance; if (taskManager == null || taskPanel == null) return; @@ -77,8 +81,29 @@ namespace TcgEngine.Client activeTasks = taskManager.GetActiveTasks(); completedTasks = taskManager.GetCompletedTasks(); - taskPanel.RefreshTasks(activeTasks); + // 用 tasks 排序 + var sortedTasks = tasks + .OrderBy(t => GetTaskSortOrder(t.status)) + .ThenBy(t => t.assignedTime) + .ToList(); + + taskPanel.allTaskData = taskManager.taskConfigs; + taskPanel.RefreshTasks(sortedTasks); } + + private int GetTaskSortOrder(TaskStatus status) + { + switch (status) + { + case TaskStatus.Completed: return 0; // 第一优先 + case TaskStatus.Active: return 1; + case TaskStatus.Claimed: return 2; + case TaskStatus.Expired: return 3; + default: return 4; + } + } + + } } \ No newline at end of file diff --git a/Assets/TcgEngine/Scripts/GameLogic/TaskManager.cs b/Assets/TcgEngine/Scripts/GameLogic/TaskManager.cs index d389a1b..c57e325 100644 --- a/Assets/TcgEngine/Scripts/GameLogic/TaskManager.cs +++ b/Assets/TcgEngine/Scripts/GameLogic/TaskManager.cs @@ -150,16 +150,16 @@ namespace TcgEngine.Gameplay foreach (var item in taskResponses) { - Debug.Log($"缓存ID处{item.id}"); + // Debug.Log($"缓存ID处{item.id}"); taskConfigs[item.id] = TaskData.CreateFromResponse(item); } - Debug.Log("共储存:" + taskConfigs.Count + "条信息"); + // Debug.Log("共储存:" + taskConfigs.Count + "条信息"); foreach (var kvp in taskConfigs) { TaskData task = kvp.Value; - Debug.Log($"分别为 {task.id}"); + // Debug.Log($"分别为 {task.id}"); } } catch (Exception e) @@ -268,6 +268,7 @@ namespace TcgEngine.Gameplay if (res.success) { Debug.Log("玩家任务已保存到服务器"); + ResetUIPanel(); } else { @@ -285,6 +286,7 @@ namespace TcgEngine.Gameplay if (Input.GetKeyDown(KeyCode.S)) { + CheckExpiredTasks(playerTasks); SavePlayerData(); } } @@ -425,6 +427,7 @@ namespace TcgEngine.Gameplay } task.status = TaskStatus.Claimed; + SavePlayerData(); return true; } @@ -470,7 +473,6 @@ namespace TcgEngine.Gameplay private void UpdateTaskProgress(TaskConditionType conditionType, string parameter1 = null, string parameter2 = null) { bool progressUpdated = false; - refreshTaskUI?.Invoke(playerTasks); foreach (var task in playerTasks) { if (task.status != TaskStatus.Active) @@ -632,11 +634,6 @@ namespace TcgEngine.Gameplay // 如过有就随机分配一个新任务 AssignDailyTaskIfNeeded(); } - - // 登录任务完成 - UpdateTaskProgress(TaskConditionType.LoginGame); - - } /// @@ -663,6 +660,8 @@ namespace TcgEngine.Gameplay lastDailyTaskAssigned = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); SavePlayerData(); Debug.Log($"分配登录任务: {loginTask.name}"); + // 登录任务完成 + UpdateTaskProgress(TaskConditionType.LoginGame); } else { @@ -688,5 +687,13 @@ namespace TcgEngine.Gameplay { return playerTasks; } + + /// + /// 重置面板 + /// + private void ResetUIPanel() + { + refreshTaskUI?.Invoke(playerTasks); + } } } \ No newline at end of file diff --git a/Assets/TcgEngine/Scripts/Tasks/TaskItem.cs b/Assets/TcgEngine/Scripts/Tasks/TaskItem.cs index 2275ce9..3c9b064 100644 --- a/Assets/TcgEngine/Scripts/Tasks/TaskItem.cs +++ b/Assets/TcgEngine/Scripts/Tasks/TaskItem.cs @@ -7,7 +7,7 @@ using UnityEngine.UI; namespace TcgEngine.UI { - public class TaskItem : MonoBehaviour + public class TaskItem : UIPanel { public string taskID; @@ -18,10 +18,20 @@ namespace TcgEngine.UI public Button reward_button; public Image reward_icon; + + public Image taskEnd_img; private PlayerTask playerTask; private TaskData taskConfig; + + protected override void Awake() + { + base.Awake(); + Show(); + taskEnd_img.gameObject.SetActive(false); + } + public void SetTask(TaskData config, PlayerTask task) { taskID = config.id; @@ -41,6 +51,11 @@ namespace TcgEngine.UI reward_button.onClick.RemoveAllListeners(); reward_button.onClick.AddListener(OnClickReward); + if (task.status == TaskStatus.Expired || task.status == TaskStatus.Claimed) + { + taskEnd_img.gameObject.SetActive(true); + } + RefreshStatus(); } @@ -59,9 +74,7 @@ namespace TcgEngine.UI progressBar_slider.value = playerTask.progress; progressBar_text.text = playerTask.progress + "/" + taskConfig.value1; } - - - + private void RewardColl(Sprite icon) { if (reward_icon != null) diff --git a/Assets/TcgEngine/Scripts/Tasks/TaskPanel.cs b/Assets/TcgEngine/Scripts/Tasks/TaskPanel.cs index 5e3a95b..d835f80 100644 --- a/Assets/TcgEngine/Scripts/Tasks/TaskPanel.cs +++ b/Assets/TcgEngine/Scripts/Tasks/TaskPanel.cs @@ -11,16 +11,12 @@ namespace TcgEngine.UI public GameObject taskItemPrefab; private Dictionary taskItems = new Dictionary(); - public Dictionary allTaskData; + public Dictionary allTaskData = new Dictionary(); protected override void Awake() { base.Awake(); - allTaskData = new Dictionary(); - TaskData[] datas = Resources.LoadAll("Tasks"); // 假设你放在 Resources/Tasks 下 - foreach (var d in datas) - { - allTaskData[d.id] = d; - } + // 清除所有子集 + ClearTasks(); } protected override void Start() @@ -29,80 +25,38 @@ namespace TcgEngine.UI Show(); } - /// - /// 初始化任务列表(只在第一次打开时用) - /// - public void ShowTasks(List playerTasks) - { - if (taskListRoot != null) - { - foreach (Transform child in taskListRoot) - { - Destroy(child.gameObject); - } - } - - ClearTasks(); - - foreach (var pTask in playerTasks) - { - GameObject gObj = Instantiate(taskItemPrefab, taskListRoot); - TaskItem item = gObj.GetComponent(); - taskItems[pTask.taskId] = item; - - TaskData data = LoadTaskDataById(pTask.taskId); - if (data != null) - { - item.SetTask(data, pTask); - } - } - } - public void RefreshTasks(List playerTasks) { - HashSet currentIds = new HashSet(); - foreach (var pTask in playerTasks) + if (playerTasks == null) return; + + ClearTasks(); + + foreach (var playerTask in playerTasks) { - if (taskItems.ContainsKey(pTask.taskId)) + if (!allTaskData.TryGetValue(playerTask.taskId,out TaskData taskConfig)) { - TaskItem item = taskItems[pTask.taskId]; - TaskData data = LoadTaskDataById(pTask.taskId); - if (data != null) - { - item.SetTask(data, pTask); - } - - currentIds .Remove(pTask.taskId); - } - else - { - GameObject gObj = Instantiate(taskItemPrefab, taskListRoot); - TaskItem item = gObj.GetComponent(); - taskItems[pTask.taskId] = item; - - TaskData data = LoadTaskDataById(pTask.taskId); - if (data != null) - item.SetTask(data, pTask); + Debug.LogWarning($"未找到配置:{playerTask.taskId}"); + continue; } - } - // Step 2: 删除那些在 playerTasks 里不存在的旧任务 - foreach (var oldId in currentIds) - { - if (taskItems.TryGetValue(oldId, out TaskItem oldItem)) + GameObject go = Instantiate(taskItemPrefab, taskListRoot); + TaskItem item = go.GetComponent(); + if (item != null) { - Destroy(oldItem.gameObject); - taskItems.Remove(oldId); + item.SetTask(taskConfig, playerTask); + taskItems[playerTask.taskId] = item; } } + } - public void ClearTasks() + private void ClearTasks() { - foreach (var item in taskItems.Values) + // 删除已有任务Item + foreach (Transform child in taskListRoot) { - Destroy(item.gameObject); + Destroy(child.gameObject); } taskItems.Clear(); } @@ -112,17 +66,6 @@ namespace TcgEngine.UI base.AfterHide(); ClearTasks(); } - - - - - - private TaskData LoadTaskDataById(string id) - { - if (allTaskData.TryGetValue(id, out TaskData data)) - return data; - return null; - } } }