From aeea1a1611db0186105c71e70dec541c07c11ec3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A3=AE2003?= <2384017988@qq.com> Date: Thu, 25 Jun 2026 17:21:39 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AD=98=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Assets/MyGame/Scripts/Net/APIManager.cs | 3 + .../MyGame/Scripts/Net/APIRequestList_Hall.cs | 12 +- .../Scripts/Net/APIResponses/HallResponses.cs | 20 ++- Assets/MyGame/Scripts/Net/APIType.cs | 5 + Assets/MyGame/aa/UI/DefaultPanel/GGL.prefab | 146 +++++++++++++++--- .../UI/DefaultPanel/GuaGuaLe/GuaGuaLeGPU.cs | 90 +++++------ .../UI/DefaultPanel/GuaGuaLe/GuaGuaLeItem.cs | 20 +++ .../GuaGuaLe/GuaGuaLeItem.cs.meta | 11 ++ 8 files changed, 230 insertions(+), 77 deletions(-) create mode 100644 Assets/MyGame/aa/UI/DefaultPanel/GuaGuaLe/GuaGuaLeItem.cs create mode 100644 Assets/MyGame/aa/UI/DefaultPanel/GuaGuaLe/GuaGuaLeItem.cs.meta diff --git a/Assets/MyGame/Scripts/Net/APIManager.cs b/Assets/MyGame/Scripts/Net/APIManager.cs index 951df8ed0..0d27541b4 100644 --- a/Assets/MyGame/Scripts/Net/APIManager.cs +++ b/Assets/MyGame/Scripts/Net/APIManager.cs @@ -68,6 +68,9 @@ namespace Assets.MyGame.Scripts.Net dic_API[APIType.Hall_GetUserTaskList] = "/api/Hall/GetUserTaskList"; dic_API[APIType.Hall_DistributeRewards] = "/api/Hall/DistributeRewards"; + // ---------------- ScratchCard ---------------- + dic_API[APIType.Hall_ScratchCardDraw] = "/api/ScratchCard/draw"; + // ---------------- HubsReceive ---------------- dic_API[APIType.Hubs_GetRoomList] = "/hubs/GetRoomList"; dic_API[APIType.Hubs_JoinRoom] = "/hubs/JoinRoom"; diff --git a/Assets/MyGame/Scripts/Net/APIRequestList_Hall.cs b/Assets/MyGame/Scripts/Net/APIRequestList_Hall.cs index e91351431..32b4d04c4 100644 --- a/Assets/MyGame/Scripts/Net/APIRequestList_Hall.cs +++ b/Assets/MyGame/Scripts/Net/APIRequestList_Hall.cs @@ -1,4 +1,4 @@ -using Assets.MyGame.Scripts.Net.API; +using Assets.MyGame.Scripts.Net.API; using Assets.MyGame.Scripts.Net.APIRequest.Objs; using Assets.MyGame.Scripts.Net.APIRequest.Params; using Assets.MyGame.Scripts.Net.APIResponses; @@ -210,6 +210,16 @@ namespace Assets.MyGame.Scripts.Net APIManager.Response(APIType.Hall_DistributeRewards, req, callback); } + + /// + /// 使用刮刮卡抽奖(GET,无参) + /// 返回:ScratchCardResult(抽奖结果:prizeType/prizeName/count/baseProduct) + /// + public static void ScratchCardDraw(Action callback) + { + APIManager.Response(APIType.Hall_ScratchCardDraw, callback); + } + #endregion } } diff --git a/Assets/MyGame/Scripts/Net/APIResponses/HallResponses.cs b/Assets/MyGame/Scripts/Net/APIResponses/HallResponses.cs index c36eaa439..05b478f92 100644 --- a/Assets/MyGame/Scripts/Net/APIResponses/HallResponses.cs +++ b/Assets/MyGame/Scripts/Net/APIResponses/HallResponses.cs @@ -1,4 +1,5 @@ -using System; +using System; +using Assets.MyGame.Scripts.Net.API.GameConfig_SubClass; namespace Assets.MyGame.Scripts.Net.APIResponses { @@ -156,4 +157,19 @@ namespace Assets.MyGame.Scripts.Net.APIResponses public string name; // 奖励名称 public PropInfo[] items; // 奖励物品 } -} + /// + /// 刮刮卡抽奖结果(接口:/api/ScratchCard/draw) + /// + [Serializable] + public class ScratchCardResult + { + /// 奖品类型 1=金币 2=钻石 3=道具 + public int prizeType; + /// 奖品名称 + public string prizeName; + /// 奖励数量 + public int count; + /// 道具信息(prizeType=3 时有值) + public BaseProduct baseProduct; + } +} \ No newline at end of file diff --git a/Assets/MyGame/Scripts/Net/APIType.cs b/Assets/MyGame/Scripts/Net/APIType.cs index 24317e676..44e8fde47 100644 --- a/Assets/MyGame/Scripts/Net/APIType.cs +++ b/Assets/MyGame/Scripts/Net/APIType.cs @@ -106,6 +106,11 @@ namespace Assets.MyGame.Scripts.Net Hall_DistributeRewards, + // ---------------- ScratchCard ---------------- + /// 使用刮刮卡抽奖(GET) + Hall_ScratchCardDraw, + + // ---------------- HubsReceive ---------------- /// 获取房间列表(GET) Hubs_GetRoomList, diff --git a/Assets/MyGame/aa/UI/DefaultPanel/GGL.prefab b/Assets/MyGame/aa/UI/DefaultPanel/GGL.prefab index 0be2ab0a5..32396eecd 100644 --- a/Assets/MyGame/aa/UI/DefaultPanel/GGL.prefab +++ b/Assets/MyGame/aa/UI/DefaultPanel/GGL.prefab @@ -147,6 +147,68 @@ MonoBehaviour: y: 0 width: 1 height: 1 +--- !u!1 &2391965727188370054 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 5708383959453866398} + - component: {fileID: 5001104637108761946} + m_Layer: 0 + m_Name: Gift + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &5708383959453866398 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2391965727188370054} + 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: 9068608665319581819} + 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: 32.5, y: -58} + m_SizeDelta: {x: 423, y: 162} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &5001104637108761946 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2391965727188370054} + 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: 0 + m_ChildForceExpandHeight: 1 + m_ChildControlWidth: 0 + m_ChildControlHeight: 0 + m_ChildScaleWidth: 0 + m_ChildScaleHeight: 0 + m_ReverseArrangement: 0 --- !u!1 &3670369079429744160 GameObject: m_ObjectHideFlags: 0 @@ -177,11 +239,11 @@ RectTransform: m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] - m_Father: {fileID: 9068608665319581819} + m_Father: {fileID: 7670511784676059837} 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: 31.500006, y: -49.000015} + m_AnchoredPosition: {x: 0, y: 8.999985} m_SizeDelta: {x: 85, y: 64} m_Pivot: {x: 0.5, y: 0.5} --- !u!222 &8027089402435724610 @@ -252,11 +314,11 @@ RectTransform: m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] - m_Father: {fileID: 9068608665319581819} + m_Father: {fileID: 7670511784676059837} 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: 32.49998, y: -92.000015} + m_AnchoredPosition: {x: 0.9999809, y: -34} m_SizeDelta: {x: 57, y: 16} m_Pivot: {x: 0.5, y: 0.5} --- !u!222 &8296661565039094048 @@ -388,9 +450,8 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: - {fileID: 7116278479721089516} - - {fileID: 7670511784676059837} - - {fileID: 3978305931316247571} - - {fileID: 5277753812324776221} + - {fileID: 5708383959453866398} + - {fileID: 1580374375004375625} - {fileID: 6533238405127315498} - {fileID: 5459618646650965046} - {fileID: 7439266752316284041} @@ -652,24 +713,14 @@ MonoBehaviour: uIEffect: 1 scratchImage: {fileID: 1182454637597247869} tmp_AwardName: {fileID: 9123422922308943981} + giftPrefab: {fileID: 322732254292001805} + giftPrefabParent: {fileID: 5708383959453866398} maskMat: {fileID: 2100000, guid: 16fb6fc82be36a540a74d11f90c0db6b, type: 2} eraseMat: {fileID: 2100000, guid: 3261f5202cdff64409572045cc75834c, type: 2} coatColor: {r: 0.7, g: 0.7, b: 0.7, a: 1} brushSize: 0.116 revealThreshold: 0.6 autoReveal: 1 - awards: - - "\u8C22\u8C22\u53C2\u4E0E" - - "\u4E00\u7B49\u5956" - - "\u4E8C\u7B49\u5956" - - "\u4E09\u7B49\u5956" - - "\u518D\u6765\u4E00\u6B21" - awardWeights: - - 0.5 - - 0.05 - - 0.1 - - 0.15 - - 0.2 onRevealed: m_PersistentCalls: m_Calls: [] @@ -748,6 +799,42 @@ MonoBehaviour: m_FillOrigin: 0 m_UseSpriteMesh: 0 m_PixelsPerUnitMultiplier: 1 +--- !u!1 &8916455877027524160 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1580374375004375625} + m_Layer: 0 + m_Name: Prefab + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 0 +--- !u!224 &1580374375004375625 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8916455877027524160} + 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: 7670511784676059837} + m_Father: {fileID: 9068608665319581819} + 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: 0, y: 0} + m_SizeDelta: {x: 100, y: 100} + m_Pivot: {x: 0.5, y: 0.5} --- !u!1 &8956164347122915666 GameObject: m_ObjectHideFlags: 0 @@ -759,6 +846,7 @@ GameObject: - component: {fileID: 7670511784676059837} - component: {fileID: 5941135501919430999} - component: {fileID: 94702547002827875} + - component: {fileID: 322732254292001805} m_Layer: 0 m_Name: NZXL_New_zljl_bg19 m_TagString: Untagged @@ -777,8 +865,10 @@ RectTransform: m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 9068608665319581819} + m_Children: + - {fileID: 3978305931316247571} + - {fileID: 5277753812324776221} + m_Father: {fileID: 1580374375004375625} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} @@ -823,3 +913,17 @@ MonoBehaviour: m_FillOrigin: 0 m_UseSpriteMesh: 0 m_PixelsPerUnitMultiplier: 1 +--- !u!114 &322732254292001805 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8956164347122915666} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: bc1a7c0767d57c048a5077dec56ed44f, type: 3} + m_Name: + m_EditorClassIdentifier: + image: {fileID: 2708368166668710266} + tmp_PropCount: {fileID: 9123422922308943981} diff --git a/Assets/MyGame/aa/UI/DefaultPanel/GuaGuaLe/GuaGuaLeGPU.cs b/Assets/MyGame/aa/UI/DefaultPanel/GuaGuaLe/GuaGuaLeGPU.cs index c64b8e08f..544e7ba30 100644 --- a/Assets/MyGame/aa/UI/DefaultPanel/GuaGuaLe/GuaGuaLeGPU.cs +++ b/Assets/MyGame/aa/UI/DefaultPanel/GuaGuaLe/GuaGuaLeGPU.cs @@ -1,3 +1,4 @@ +using Assets.MyGame.Scripts.Net; using TMPro; using UnityEngine; using UnityEngine.EventSystems; @@ -10,17 +11,14 @@ using UnityEngine.UI; /// RawImage (prizeImage) ← 最下层:奖品图 /// Text (tmp_AwardName) ← 中间层:奖品文字 /// RawImage (scratchImage) ← 最上层:涂层遮罩(挂本脚本) -/// -/// 原理: -/// 涂层遮罩用 ScratchMask.shader,遮罩 RT 全白 = 不透明(未刮), -/// 全黑 = 透明(已刮)。刮擦通过 Graphics.Blit + ScratchErase.shader -/// 在 GPU 内完成,零 CPU 像素操作。 /// public class GuaGuaLeGPU : SubUIBase, IPointerDownHandler, IDragHandler { [Header("UI 引用(必填)")] public RawImage scratchImage; // 最上层:涂层遮罩(挂此脚本) - public TextMeshProUGUI tmp_AwardName; // 中间层:奖品文字 + public TextMeshProUGUI tmp_AwardName; // 中间层:奖品文字 + public GuaGuaLeItem giftPrefab; // 奖品预制体(用于显示奖品图片) + public Transform giftPrefabParent; [Header("材质(模板)")] public Material maskMat; // 使用 ScratchMask.shader(涂层遮罩) @@ -36,10 +34,6 @@ public class GuaGuaLeGPU : SubUIBase, IPointerDownHandler, IDragHandler [Range(0f, 1f)] public float revealThreshold = 0.6f; public bool autoReveal = true; - [Header("奖品配置")] - public string[] awards = { "谢谢参与", "一等奖", "二等奖", "三等奖", "再来一次" }; - public float[] awardWeights = { 0.50f, 0.05f, 0.10f, 0.15f, 0.20f }; - [Header("事件")] public UnityEngine.Events.UnityEvent onRevealed; @@ -59,30 +53,24 @@ public class GuaGuaLeGPU : SubUIBase, IPointerDownHandler, IDragHandler private Texture2D progressReadTex; private int dragCount; + protected override void OnShow(object args = null) { base.OnShow(args); ResetCard(); } + private void Start() { if (scratchImage == null) { Debug.LogError("[GPU] scratchImage 为空!"); return; } if (maskMat == null) { Debug.LogError("[GPU] maskMat 为空!"); return; } if (eraseMat == null) { Debug.LogError("[GPU] eraseMat 为空!"); return; } - if (awardWeights == null || awardWeights.Length != awards.Length) - { - awardWeights = new float[awards.Length]; - float w = 1f / Mathf.Max(1, awards.Length); - for (int i = 0; i < awardWeights.Length; i++) awardWeights[i] = w; - } - InitCard(); } private void InitCard() { - // 1. 遮罩 RT(全白 = 未刮,不透明) maskRT = new RenderTexture(rtWidth, rtHeight, 0, RenderTextureFormat.ARGB32) { filterMode = FilterMode.Bilinear @@ -90,9 +78,6 @@ public class GuaGuaLeGPU : SubUIBase, IPointerDownHandler, IDragHandler maskRT.Create(); ClearRT(maskRT, Color.white); - - - // 3. 最上层:涂层遮罩材质(实例化,避免 UGUI 材质共享问题) instanceMaskMat = new Material(maskMat); instanceMaskMat.SetTexture("_MaskTex", maskRT); instanceMaskMat.SetColor("_CoatColor", coatColor); @@ -100,20 +85,13 @@ public class GuaGuaLeGPU : SubUIBase, IPointerDownHandler, IDragHandler scratchImage.material = instanceMaskMat; scratchImage.texture = null; - // 4. 擦除材质实例 instanceEraseMat = new Material(eraseMat); instanceEraseMat.SetFloat("_BrushSize", brushSize); - // 5. 摇奖 - currentAward = RollAward(); - if (tmp_AwardName != null) - tmp_AwardName.text = currentAward; - - // 6. 进度读取用纹理 progressReadTex = new Texture2D(rtWidth, rtHeight, TextureFormat.ARGB32, false); ResetState(); - Debug.Log($"[GPU] 初始化完成 {rtWidth}x{rtHeight}"); + FetchAward(); } private void ResetState() @@ -124,6 +102,34 @@ public class GuaGuaLeGPU : SubUIBase, IPointerDownHandler, IDragHandler dragCount = 0; } + // ================================================================ + // API 抽奖 + // ================================================================ + + private void FetchAward() + { + APIRequestList.ScratchCardDraw(result => + { + if (result == null) return; + + currentAward = result.prizeName ?? "谢谢参与"; + if (tmp_AwardName != null) + tmp_AwardName.text = currentAward; + + // 清除旧的奖励物品 + for (int i = giftPrefabParent.childCount - 1; i >= 0; i--) + Destroy(giftPrefabParent.GetChild(i).gameObject); + + // 显示奖品图片(baseProduct.imageUrl) + string imgUrl = result.baseProduct?.imageUrl; + if (!string.IsNullOrEmpty(imgUrl) && giftPrefab != null) + { + var item = Instantiate(giftPrefab, giftPrefabParent); + item.Init(imgUrl, result.count); + } + }); + } + // ================================================================ // 公开方法 // ================================================================ @@ -135,12 +141,10 @@ public class GuaGuaLeGPU : SubUIBase, IPointerDownHandler, IDragHandler ClearRT(maskRT, Color.white); ResetState(); - currentAward = RollAward(); - if (tmp_AwardName != null) - tmp_AwardName.text = currentAward; - if (instanceMaskMat != null) instanceMaskMat.SetColor("_CoatColor", coatColor); + + FetchAward(); } public void RevealAll() @@ -284,26 +288,6 @@ public class GuaGuaLeGPU : SubUIBase, IPointerDownHandler, IDragHandler return uv.x >= 0f && uv.x <= 1f && uv.y >= 0f && uv.y <= 1f; } - private string RollAward() - { - if (awards == null || awards.Length == 0) return "谢谢参与"; - int n = Mathf.Min(awards.Length, awardWeights == null ? 0 : awardWeights.Length); - if (n <= 0) return awards[0]; - - float sum = 0f; - for (int i = 0; i < n; i++) sum += Mathf.Max(0f, awardWeights[i]); - if (sum <= 0f) return awards[0]; - - float r = Random.value * sum; - float acc = 0f; - for (int i = 0; i < n; i++) - { - acc += Mathf.Max(0f, awardWeights[i]); - if (r <= acc) return awards[i]; - } - return awards[n - 1]; - } - public string CurrentAward => currentAward; public bool IsRevealed => isRevealed; diff --git a/Assets/MyGame/aa/UI/DefaultPanel/GuaGuaLe/GuaGuaLeItem.cs b/Assets/MyGame/aa/UI/DefaultPanel/GuaGuaLe/GuaGuaLeItem.cs new file mode 100644 index 000000000..8da7361ff --- /dev/null +++ b/Assets/MyGame/aa/UI/DefaultPanel/GuaGuaLe/GuaGuaLeItem.cs @@ -0,0 +1,20 @@ +using Assets.Framework.Tool; +using System.Collections; +using System.Collections.Generic; +using TMPro; +using UnityEngine; +using UnityEngine.UI; + +public class GuaGuaLeItem : MonoBehaviour +{ + public Image image; + public TextMeshProUGUI tmp_PropCount; + public void Init(string url,int count) + { + WebTool.DownImage(url, (texture) => + { + image.sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), Vector2.zero); + }); + tmp_PropCount.text = count.ToString(); + } +} diff --git a/Assets/MyGame/aa/UI/DefaultPanel/GuaGuaLe/GuaGuaLeItem.cs.meta b/Assets/MyGame/aa/UI/DefaultPanel/GuaGuaLe/GuaGuaLeItem.cs.meta new file mode 100644 index 000000000..61523c907 --- /dev/null +++ b/Assets/MyGame/aa/UI/DefaultPanel/GuaGuaLe/GuaGuaLeItem.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bc1a7c0767d57c048a5077dec56ed44f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: