This commit is contained in:
2026-06-25 17:21:39 +08:00
parent 51fdabc2e6
commit aeea1a1611
8 changed files with 230 additions and 77 deletions
+3
View File
@@ -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";
@@ -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<RewardInfo>(APIType.Hall_DistributeRewards, req, callback);
}
/// <summary>
/// 使用刮刮卡抽奖(GET,无参)
/// 返回:ScratchCardResult(抽奖结果:prizeType/prizeName/count/baseProduct)
/// </summary>
public static void ScratchCardDraw(Action<ScratchCardResult> callback)
{
APIManager.Response<ScratchCardResult>(APIType.Hall_ScratchCardDraw, callback);
}
#endregion
}
}
@@ -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; // 奖励物品
}
}
/// <summary>
/// 刮刮卡抽奖结果(接口:/api/ScratchCard/draw)
/// </summary>
[Serializable]
public class ScratchCardResult
{
/// <summary>奖品类型 1=金币 2=钻石 3=道具</summary>
public int prizeType;
/// <summary>奖品名称</summary>
public string prizeName;
/// <summary>奖励数量</summary>
public int count;
/// <summary>道具信息(prizeType=3 时有值)</summary>
public BaseProduct baseProduct;
}
}
+5
View File
@@ -106,6 +106,11 @@ namespace Assets.MyGame.Scripts.Net
Hall_DistributeRewards,
// ---------------- ScratchCard ----------------
/// <summary>使用刮刮卡抽奖(GET)</summary>
Hall_ScratchCardDraw,
// ---------------- HubsReceive ----------------
/// <summary>获取房间列表(GET)</summary>
Hubs_GetRoomList,
+125 -21
View File
@@ -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}
@@ -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 像素操作。
/// </summary>
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;
@@ -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();
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bc1a7c0767d57c048a5077dec56ed44f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: