From 8506590b12282b52026113a0b8ee48c82a3fe122 Mon Sep 17 00:00:00 2001 From: YiHan0621 <2857295085@qq.com> Date: Fri, 12 Sep 2025 11:39:17 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=BB=E9=A1=B5=E4=B8=8ETask=E4=BB=BB?= =?UTF-8?q?=E5=8A=A1=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Prefabs/UI/Task/RewardItem.prefab | 178 ++++++++++++++++++ .../Prefabs/UI/Task/RewardItem.prefab.meta | 7 + .../TcgEngine/Prefabs/UI/Task/TaskItem.prefab | 52 +++-- Assets/TcgEngine/Resources/TaskReward.meta | 8 + .../Resources/TaskReward/TaskReward.asset | 19 ++ .../TaskReward/TaskReward.asset.meta | 8 + Assets/TcgEngine/Scenes/Menu/Menu.unity | 3 +- Assets/TcgEngine/Scripts/Api/ApiClient.cs | 2 +- Assets/TcgEngine/Scripts/Data/TaskData.cs | 3 +- .../TcgEngine/Scripts/Data/TaskRewardData.cs | 44 +++++ .../Scripts/Data/TaskRewardData.cs.meta | 3 + .../Scripts/GameLogic/TaskManager.cs | 22 ++- .../Scripts/Menu/LeaderboardPanel.cs | 27 +-- Assets/TcgEngine/Scripts/Menu/UIFrame.cs | 29 +++ Assets/TcgEngine/Scripts/Menu/UIFrame.cs.meta | 11 ++ Assets/TcgEngine/Scripts/Tasks/TaskItem.cs | 25 ++- Assets/TcgEngine/Scripts/Tasks/TaskReward.cs | 52 +++++ .../Scripts/Tasks/TaskReward.cs.meta | 11 ++ .../GlobalButton/global_Leaderboard.png | Bin 0 -> 9577 bytes .../GlobalButton/global_Leaderboard.png.meta | 135 +++++++++++++ 20 files changed, 579 insertions(+), 60 deletions(-) create mode 100644 Assets/TcgEngine/Prefabs/UI/Task/RewardItem.prefab create mode 100644 Assets/TcgEngine/Prefabs/UI/Task/RewardItem.prefab.meta create mode 100644 Assets/TcgEngine/Resources/TaskReward.meta create mode 100644 Assets/TcgEngine/Resources/TaskReward/TaskReward.asset create mode 100644 Assets/TcgEngine/Resources/TaskReward/TaskReward.asset.meta create mode 100644 Assets/TcgEngine/Scripts/Data/TaskRewardData.cs create mode 100644 Assets/TcgEngine/Scripts/Data/TaskRewardData.cs.meta create mode 100644 Assets/TcgEngine/Scripts/Menu/UIFrame.cs create mode 100644 Assets/TcgEngine/Scripts/Menu/UIFrame.cs.meta create mode 100644 Assets/TcgEngine/Scripts/Tasks/TaskReward.cs create mode 100644 Assets/TcgEngine/Scripts/Tasks/TaskReward.cs.meta create mode 100644 Assets/TcgEngine/Sprites/GlobalButton/global_Leaderboard.png create mode 100644 Assets/TcgEngine/Sprites/GlobalButton/global_Leaderboard.png.meta diff --git a/Assets/TcgEngine/Prefabs/UI/Task/RewardItem.prefab b/Assets/TcgEngine/Prefabs/UI/Task/RewardItem.prefab new file mode 100644 index 0000000..9483940 --- /dev/null +++ b/Assets/TcgEngine/Prefabs/UI/Task/RewardItem.prefab @@ -0,0 +1,178 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &3773603359716521685 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 5844164435676398261} + - component: {fileID: 6774589803606362231} + - component: {fileID: 4748133634100025909} + - component: {fileID: 8170459783435472423} + m_Layer: 5 + m_Name: RewardItem + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &5844164435676398261 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3773603359716521685} + 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: + - {fileID: 2013309795088359583} + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 56, y: 56} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &6774589803606362231 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3773603359716521685} + m_CullTransparentMesh: 1 +--- !u!114 &4748133634100025909 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3773603359716521685} + 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: 1, g: 1, b: 1, a: 1} + 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: bf707d878df66f9439ba474fb8d9ef55, 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!114 &8170459783435472423 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3773603359716521685} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 55af7dcd22f203d43b3ff26368c1ef5b, type: 3} + m_Name: + m_EditorClassIdentifier: + database: {fileID: 11400000, guid: d87b140f0a18c5b42b9cfa74e5448e95, type: 2} + rewardType: 0 + prizeAmount: 0 + rewardIcon: {fileID: 4748133634100025909} + amountText: {fileID: 4199357195424995409} + fixedHeight: 56 +--- !u!1 &6776010374572791816 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2013309795088359583} + - component: {fileID: 6943656237734908692} + - component: {fileID: 4199357195424995409} + m_Layer: 5 + m_Name: Text (Legacy) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &2013309795088359583 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6776010374572791816} + 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: 5844164435676398261} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 1, y: 0} + m_AnchorMax: {x: 1, y: 0} + m_AnchoredPosition: {x: -28, y: 15} + m_SizeDelta: {x: 56, y: 30} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &6943656237734908692 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6776010374572791816} + m_CullTransparentMesh: 1 +--- !u!114 &4199357195424995409 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6776010374572791816} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 16 + m_FontStyle: 1 + m_BestFit: 0 + m_MinSize: 0 + m_MaxSize: 40 + m_Alignment: 8 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: 100 diff --git a/Assets/TcgEngine/Prefabs/UI/Task/RewardItem.prefab.meta b/Assets/TcgEngine/Prefabs/UI/Task/RewardItem.prefab.meta new file mode 100644 index 0000000..32f12e7 --- /dev/null +++ b/Assets/TcgEngine/Prefabs/UI/Task/RewardItem.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 29d0d9614b5b8f542aff9d019ec8ce8d +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TcgEngine/Prefabs/UI/Task/TaskItem.prefab b/Assets/TcgEngine/Prefabs/UI/Task/TaskItem.prefab index 4b16b6a..7dc21c3 100644 --- a/Assets/TcgEngine/Prefabs/UI/Task/TaskItem.prefab +++ b/Assets/TcgEngine/Prefabs/UI/Task/TaskItem.prefab @@ -17,7 +17,7 @@ GameObject: m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 - m_IsActive: 1 + m_IsActive: 0 --- !u!224 &284419844733056354 RectTransform: m_ObjectHideFlags: 0 @@ -158,8 +158,8 @@ RectTransform: m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} - m_AnchoredPosition: {x: 23.84, y: 46.900017} - m_SizeDelta: {x: 153.18, y: 35.6} + m_AnchoredPosition: {x: 23.84, y: 39.894127} + m_SizeDelta: {x: 153.18, y: 49.6118} m_Pivot: {x: 0.5, y: 0.5} --- !u!222 &5317638606691184681 CanvasRenderer: @@ -191,18 +191,18 @@ MonoBehaviour: m_Calls: [] m_FontData: m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} - m_FontSize: 22 + m_FontSize: 20 m_FontStyle: 0 m_BestFit: 0 m_MinSize: 2 m_MaxSize: 40 - m_Alignment: 3 + m_Alignment: 0 m_AlignByGeometry: 0 m_RichText: 1 m_HorizontalOverflow: 0 m_VerticalOverflow: 0 m_LineSpacing: 1 - m_Text: "\u6D88\u706D\u6240\u6709\u654C\u4EBA" + m_Text: "\u53EC\u552410\u4E2A\u738B\u56FD\u519B\u6216\u81EA\u7531\u4EBA\u82F1\u96C4" --- !u!1 &5317638606723811022 GameObject: m_ObjectHideFlags: 0 @@ -240,7 +240,7 @@ RectTransform: m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} - m_AnchoredPosition: {x: 13.24, y: 16.9} + m_AnchoredPosition: {x: 13.24, y: 6.3} m_SizeDelta: {x: 127.33, y: 12.6} m_Pivot: {x: 0.5, y: 0.5} --- !u!114 &5317638606723811020 @@ -468,7 +468,7 @@ GameObject: m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 - m_IsActive: 1 + m_IsActive: 0 --- !u!224 &5317638607177714484 RectTransform: m_ObjectHideFlags: 0 @@ -950,8 +950,9 @@ MonoBehaviour: progressBar_slider: {fileID: 5317638606723811020} progressBar_text: {fileID: 5317638606810153107} reward_button: {fileID: 4730874702436785540} - reward_icon: {fileID: 5317638608707530455} taskEnd_img: {fileID: 6541735992704929191} + rewardItem: {fileID: 3773603359716521685, guid: 29d0d9614b5b8f542aff9d019ec8ce8d, + type: 3} --- !u!225 &5368359024977481613 CanvasGroup: m_ObjectHideFlags: 0 @@ -976,6 +977,7 @@ GameObject: - component: {fileID: 5317638608707530452} - component: {fileID: 5317638608707530455} - component: {fileID: 4730874702436785540} + - component: {fileID: 1766748350975125263} m_Layer: 5 m_Name: Reward m_TagString: Untagged @@ -1000,8 +1002,8 @@ RectTransform: 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: 3.1375, y: -112.3} - m_SizeDelta: {x: 69.7, y: 69.7} + m_AnchoredPosition: {x: 3.1375, y: -118} + m_SizeDelta: {x: 162.8714, y: 69.7} m_Pivot: {x: 0.5, y: 0.5} --- !u!222 &5317638608707530452 CanvasRenderer: @@ -1024,7 +1026,7 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: m_Material: {fileID: 0} - m_Color: {r: 1, g: 1, b: 1, a: 1} + m_Color: {r: 0.5, g: 0.5, b: 0.5, a: 0} m_RaycastTarget: 1 m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} m_Maskable: 1 @@ -1085,6 +1087,32 @@ MonoBehaviour: m_OnClick: m_PersistentCalls: m_Calls: [] +--- !u!114 &1766748350975125263 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5317638608707530441} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 30649d3a9faa99c48a7b1166b86bf2a0, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_ChildAlignment: 4 + m_Spacing: 0 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 1 + m_ChildControlWidth: 0 + m_ChildControlHeight: 0 + m_ChildScaleWidth: 0 + m_ChildScaleHeight: 0 + m_ReverseArrangement: 0 --- !u!1 &6862293603468694699 GameObject: m_ObjectHideFlags: 0 diff --git a/Assets/TcgEngine/Resources/TaskReward.meta b/Assets/TcgEngine/Resources/TaskReward.meta new file mode 100644 index 0000000..8d6681d --- /dev/null +++ b/Assets/TcgEngine/Resources/TaskReward.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c78997bb3ac4c4440a7d4efefec17f69 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TcgEngine/Resources/TaskReward/TaskReward.asset b/Assets/TcgEngine/Resources/TaskReward/TaskReward.asset new file mode 100644 index 0000000..7372fba --- /dev/null +++ b/Assets/TcgEngine/Resources/TaskReward/TaskReward.asset @@ -0,0 +1,19 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 3b5b19a5996046508584e1eb649f43dd, type: 3} + m_Name: TaskReward + m_EditorClassIdentifier: + entries: + - type: 0 + icon: {fileID: 21300000, guid: bf707d878df66f9439ba474fb8d9ef55, type: 3} + - type: 1 + icon: {fileID: 21300000, guid: 9f88fcf9a8fd4114ba8a71a53024535b, type: 3} diff --git a/Assets/TcgEngine/Resources/TaskReward/TaskReward.asset.meta b/Assets/TcgEngine/Resources/TaskReward/TaskReward.asset.meta new file mode 100644 index 0000000..5ec3e49 --- /dev/null +++ b/Assets/TcgEngine/Resources/TaskReward/TaskReward.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d87b140f0a18c5b42b9cfa74e5448e95 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TcgEngine/Scenes/Menu/Menu.unity b/Assets/TcgEngine/Scenes/Menu/Menu.unity index 6b769c9..5388691 100644 --- a/Assets/TcgEngine/Scenes/Menu/Menu.unity +++ b/Assets/TcgEngine/Scenes/Menu/Menu.unity @@ -57205,7 +57205,6 @@ MonoBehaviour: ladderRank: {fileID: 360370754} lines: [] ladderLines: [] - returnToHome_button: {fileID: 1260207039} hideGameObject: - {fileID: 1674082196} - {fileID: 0} @@ -57219,7 +57218,7 @@ CanvasGroup: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 4526323995250171124} m_Enabled: 1 - m_Alpha: 0 + m_Alpha: 1 m_Interactable: 1 m_BlocksRaycasts: 1 m_IgnoreParentGroups: 0 diff --git a/Assets/TcgEngine/Scripts/Api/ApiClient.cs b/Assets/TcgEngine/Scripts/Api/ApiClient.cs index 44a5aca..1d95711 100644 --- a/Assets/TcgEngine/Scripts/Api/ApiClient.cs +++ b/Assets/TcgEngine/Scripts/Api/ApiClient.cs @@ -241,7 +241,7 @@ namespace TcgEngine if (res.success) { udata = ApiTool.JsonToObject(res.data); - Debug.Log($"获取玩家数据:{res.data}"); + // Debug.Log($"获取玩家数据:{res.data}"); } return udata; diff --git a/Assets/TcgEngine/Scripts/Data/TaskData.cs b/Assets/TcgEngine/Scripts/Data/TaskData.cs index eee2582..63f67c1 100644 --- a/Assets/TcgEngine/Scripts/Data/TaskData.cs +++ b/Assets/TcgEngine/Scripts/Data/TaskData.cs @@ -94,7 +94,8 @@ namespace TcgEngine public enum TaskRewardType { - Coins = 0, // 金币 + Coins = 0, // 金币 + Crystal = 1, // 后续可扩展其他奖励类型 } diff --git a/Assets/TcgEngine/Scripts/Data/TaskRewardData.cs b/Assets/TcgEngine/Scripts/Data/TaskRewardData.cs new file mode 100644 index 0000000..584a765 --- /dev/null +++ b/Assets/TcgEngine/Scripts/Data/TaskRewardData.cs @@ -0,0 +1,44 @@ +using System.Collections.Generic; +using UnityEngine; +using TcgEngine.UI; + +namespace TcgEngine +{ + + [System.Serializable] + public class PrizeIconEntry + { + public TaskRewardType type; + public Sprite icon; + } + + [CreateAssetMenu(fileName = "NewTaskRewardData", menuName = "TcgEngine/TaskRewardData")] + public class TaskRewardData : ScriptableObject + { + public PrizeIconEntry[] entries; + + private Dictionary iconDict = new Dictionary(); + + public void Init() + { + iconDict.Clear(); + foreach (var entry in entries) + { + Debug.Log($"录入: {entry.type} => {entry.icon?.name}"); + iconDict[entry.type] = entry.icon; + } + } + + public Sprite GetIcon(TaskRewardType type) + { + if (iconDict.Count == 0) Init(); + + if (iconDict.TryGetValue(type, out Sprite sprite)) + return sprite; + + Debug.LogWarning($"未找到 {type} 的图标,请检查 TaskRewardData 的 entries 配置"); + return null; + } + + } +} \ No newline at end of file diff --git a/Assets/TcgEngine/Scripts/Data/TaskRewardData.cs.meta b/Assets/TcgEngine/Scripts/Data/TaskRewardData.cs.meta new file mode 100644 index 0000000..4fdd4e4 --- /dev/null +++ b/Assets/TcgEngine/Scripts/Data/TaskRewardData.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 3b5b19a5996046508584e1eb649f43dd +timeCreated: 1757580421 \ No newline at end of file diff --git a/Assets/TcgEngine/Scripts/GameLogic/TaskManager.cs b/Assets/TcgEngine/Scripts/GameLogic/TaskManager.cs index f6adaf6..4964e12 100644 --- a/Assets/TcgEngine/Scripts/GameLogic/TaskManager.cs +++ b/Assets/TcgEngine/Scripts/GameLogic/TaskManager.cs @@ -422,31 +422,37 @@ namespace TcgEngine.Gameplay } task.status = TaskStatus.Claimed; - SavePlayerData(); return true; } private void GiveReward(TaskRewardType rewardType, int amount) { + UserData userData = Authenticator.Get().UserData; // 根据奖励类型发放奖励 switch (rewardType) { case TaskRewardType.Coins: // 增加金币(需要与游戏现有金币系统集成) - UserData userData = Authenticator.Get().UserData; + if (userData != null) { userData.coins += amount; Debug.Log($"Gave {amount} coins as reward"); - - // 保存用户数据更新 - if (ApiClient.Get() != null && ApiClient.Get().IsLoggedIn()) - { - Authenticator.Get().SaveUserData(); - } } break; + case TaskRewardType.Crystal: + if (userData != null) + { + userData.crystal += amount; + Debug.Log($"获取{amount}个钻石"); + } + break; + } + // 保存用户数据更新 + if (ApiClient.Get() != null && ApiClient.Get().IsLoggedIn()) + { + Authenticator.Get().SaveUserData(); } } diff --git a/Assets/TcgEngine/Scripts/Menu/LeaderboardPanel.cs b/Assets/TcgEngine/Scripts/Menu/LeaderboardPanel.cs index 9d5c946..ef60edb 100644 --- a/Assets/TcgEngine/Scripts/Menu/LeaderboardPanel.cs +++ b/Assets/TcgEngine/Scripts/Menu/LeaderboardPanel.cs @@ -37,9 +37,6 @@ namespace TcgEngine.UI public List lines = new List(); public List ladderLines = new List(); - - [Header("返回主页")] - public Button returnToHome_button; private const string DefaultAvatarId = "bear"; @@ -59,28 +56,6 @@ namespace TcgEngine.UI my_line.onClick += OnClickLine; my_ladderLine.onClick += OnClickRankLine; InitLines(); - - returnToHome_button.onClick.AddListener(OnReturnToHome); - } - - /// - /// 返回主页 - /// - public void OnReturnToHome() - { - isHideObject = !isHideObject; - if (isHideObject) - { - Show(); - } - else - { - Hide(); - } - foreach (var obj in hideGameObject) - { - obj.SetActive(!isHideObject); - } } private void OnDestroy() @@ -257,7 +232,7 @@ namespace TcgEngine.UI } } - // + // private void RankPanelColl() // { // if (isLadderRank) diff --git a/Assets/TcgEngine/Scripts/Menu/UIFrame.cs b/Assets/TcgEngine/Scripts/Menu/UIFrame.cs new file mode 100644 index 0000000..c397d30 --- /dev/null +++ b/Assets/TcgEngine/Scripts/Menu/UIFrame.cs @@ -0,0 +1,29 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.UI; + +namespace TcgEngine.UI +{ + public class UIFrame : UIPanel + { + public Button uiFrameHideButton; + + protected override void Awake() + { + base.Awake(); + Hide(); + } + + protected override void Start() + { + uiFrameHideButton.onClick.AddListener(OnUiFrameHide); + } + + private void OnUiFrameHide() + { + Hide(); + } + } + +} diff --git a/Assets/TcgEngine/Scripts/Menu/UIFrame.cs.meta b/Assets/TcgEngine/Scripts/Menu/UIFrame.cs.meta new file mode 100644 index 0000000..8bbdb51 --- /dev/null +++ b/Assets/TcgEngine/Scripts/Menu/UIFrame.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9379c33c33779f64a94d441f6a521411 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TcgEngine/Scripts/Tasks/TaskItem.cs b/Assets/TcgEngine/Scripts/Tasks/TaskItem.cs index 3c9b064..0de8cb7 100644 --- a/Assets/TcgEngine/Scripts/Tasks/TaskItem.cs +++ b/Assets/TcgEngine/Scripts/Tasks/TaskItem.cs @@ -17,13 +17,13 @@ namespace TcgEngine.UI public Text progressBar_text; public Button reward_button; - public Image reward_icon; public Image taskEnd_img; private PlayerTask playerTask; private TaskData taskConfig; + public GameObject rewardItem; protected override void Awake() { @@ -50,12 +50,25 @@ namespace TcgEngine.UI reward_button.interactable = task.status == TaskStatus.Completed; reward_button.onClick.RemoveAllListeners(); reward_button.onClick.AddListener(OnClickReward); + + // 奖品 + for (int i = 0; i < config.rewardTypes.Length; i++) + { + TaskRewardType rewardType = config.rewardTypes[i]; + int rewardNum = (config.rewardNums != null && i < config.rewardNums.Length) + ? config.rewardNums[i] : 1; // 没配数量就默认为1 + GameObject go = Instantiate(rewardItem, reward_button.transform); + var reward = go.GetComponent(); + reward.SetPrize(rewardType, rewardNum, reward_button.interactable); // 改成传两个参数 + } + if (task.status == TaskStatus.Expired || task.status == TaskStatus.Claimed) { taskEnd_img.gameObject.SetActive(true); } - + + RefreshStatus(); } @@ -74,13 +87,5 @@ namespace TcgEngine.UI progressBar_slider.value = playerTask.progress; progressBar_text.text = playerTask.progress + "/" + taskConfig.value1; } - - private void RewardColl(Sprite icon) - { - if (reward_icon != null) - { - reward_icon.sprite = icon; - } - } } } \ No newline at end of file diff --git a/Assets/TcgEngine/Scripts/Tasks/TaskReward.cs b/Assets/TcgEngine/Scripts/Tasks/TaskReward.cs new file mode 100644 index 0000000..2f01d3c --- /dev/null +++ b/Assets/TcgEngine/Scripts/Tasks/TaskReward.cs @@ -0,0 +1,52 @@ +using System; +using UnityEngine; +using UnityEngine.UI; + +namespace TcgEngine.UI +{ + public class TaskReward : MonoBehaviour + { + public TaskRewardData database; // 存放所有奖励图标的 ScriptableObject + + public Image rewardIcon; // 图标 Image + public Text amountText; // 数量文本 + public float fixedHeight = 80f; // 固定高度 + + private RectTransform rect; + + public void SetPrize(TaskRewardType type, int amount,bool isVis) + { + if (!isVis) + { + rewardIcon.color = Color.gray; + amountText.color = Color.gray; + } + else + { + rewardIcon.color = Color.white; + amountText.color = Color.white; + } + + + // 图标 + Sprite sprite = database.GetIcon(type); + rewardIcon.sprite = sprite; + + // 数量 + if (amountText != null) + { + amountText.text = amount > 1 ? "x" + amount.ToString() : ""; + } + + // 高度固定80,等比例缩放 + if (sprite != null) + { + float ratio = sprite.rect.width / sprite.rect.height; + + rect = rewardIcon.GetComponent(); + rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, fixedHeight); + rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, fixedHeight * ratio); + } + } + } +} \ No newline at end of file diff --git a/Assets/TcgEngine/Scripts/Tasks/TaskReward.cs.meta b/Assets/TcgEngine/Scripts/Tasks/TaskReward.cs.meta new file mode 100644 index 0000000..f3ed13f --- /dev/null +++ b/Assets/TcgEngine/Scripts/Tasks/TaskReward.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 55af7dcd22f203d43b3ff26368c1ef5b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TcgEngine/Sprites/GlobalButton/global_Leaderboard.png b/Assets/TcgEngine/Sprites/GlobalButton/global_Leaderboard.png new file mode 100644 index 0000000000000000000000000000000000000000..06f644cb773a2b2b2224f3b09c3ef2dace294cec GIT binary patch literal 9577 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