using Assets.MyGame.Scripts.Net; using Assets.MyGame.Scripts.Net.API.GameConfig_SubClass; using Assets.MyGame.Scripts.Net.APIResponses; using DG.Tweening; using System; using System.Collections; using System.Collections.Generic; using TMPro; using UnityEngine; using UnityEngine.UI; public class UIHome_BY_UISignViewPanel : SubUIBase { //text_CoinNums是转盘各个位置的详细值 他从GameManager的activityConfig里面读取signActivityConfig.days后端配置的个数和text_CoinNums的个数是对应的 这里赋值的时候需要加上其他的数据公式是 值+值*GameManager的gameConfig的vip的signInAdd签到加成 /*签到API已封装在APIRequestList.SignIn(GET) 响应为SignRewardResult:{day, gold, diamond, product}——day=本次签到天数(1~7),转盘直接按day停靠格子(不再金额反查)*/ //SLZPDieEvent这个脚本有之前写好的多层转盘的逻辑 签到这里只有单层 你可以直接看一下里面正确的 public List text_CoinNums; public List text_CoinNums_TMP; public TextMeshProUGUI tmp_VipJiaCheng; // 显示VIP签到加成百分比 public TextMeshProUGUI tmp_EndCoin; // 显示最终奖励金币数 public Button btn_ChouJiang; public GameObject zhuanPan; Dictionary day_singConfig; // key=第几天(1~7) [Header("转盘参数(参照SLZPDieEvent)")] public int spinRounds = 5; // 到达目标前转的圈数 public float rotateDuration = 2f; // 旋转总时长 public float dir = -1f; // 旋转方向(-1逆时针,1顺时针) private bool isSpinning; public override void Awake() { base.Awake(); btn_ChouJiang.onClick.AddListener(OnChouJiangClick); } protected override void OnShow(object args = null) { base.OnShow(args); OnChouJiangClick(); RefreshPanel(); } private void RefreshPanel() { BuildDaySignConfig(); UpdateSlotTexts(); UpdateBtnState(); UpdateVipAddText(); } /// 显示VIP签到加成百分比(signInAdd 0.15 → +15%) private void UpdateVipAddText() { if (tmp_VipJiaCheng == null) return; double add = GetSignInAdd(); tmp_VipJiaCheng.text = $"+{add * 100:0}%"; } /// 从GameManager的activityConfig读取signActivityConfig.days,按day建立字典 private void BuildDaySignConfig() { day_singConfig = new Dictionary(); var days = GameManager.Instance.activityConfig?.signActivityConfig?.days; if (days == null) return; foreach (var cfg in days) { if (cfg == null) continue; day_singConfig[cfg.day] = cfg; } } /// 当前用户的VIP签到加成(gameConfig.vipLevelConfigs按用户vipLevel匹配signInAdd) private double GetSignInAdd() { var vipConfigs = GameManager.Instance.gameConfig?.vipLevelConfigs; if (vipConfigs == null || vipConfigs.Count == 0) return 0; var user = GameManager.Instance.user; if (user?.assets == null) return 0; var vipCfg = vipConfigs.Find(v => v.level == user.assets.vipLevel); return vipCfg?.signInAdd ?? 0; } /// 转盘格子数量:UGUI Text列表有绑定就用它,否则用TMP列表 private int SlotCount() { if (text_CoinNums != null && text_CoinNums.Count > 0) return text_CoinNums.Count; return text_CoinNums_TMP != null ? text_CoinNums_TMP.Count : 0; } /// 给第index个转盘格子设置文本(兼容UGUI Text与TMP) private void SetSlotText(int index, string value) { if (text_CoinNums != null && index < text_CoinNums.Count) text_CoinNums[index].text = value; else if (text_CoinNums_TMP != null && index < text_CoinNums_TMP.Count) text_CoinNums_TMP[index].text = value; } /// 转盘格子赋值:金币值+值*signInAdd(VIP签到加成),按day排序后与text_CoinNums一一对应 private void UpdateSlotTexts() { int slotCount = SlotCount(); if (day_singConfig == null || day_singConfig.Count == 0 || slotCount == 0) return; var list = new List(day_singConfig.Values); list.Sort((a, b) => a.day - b.day); double add = GetSignInAdd(); int count = Mathf.Min(list.Count, slotCount); for (int i = 0; i < count; i++) { long gold = GetGiftGold(list[i]); long showGold = gold + (long)Math.Round(gold * add); SetSlotText(i, FormatGold(showGold)); } } /// 取单日配置中的金币奖励数(giftList 中 type=1 金币项;无金币项返回0) private static long GetGiftGold(SignConfig cfg) { if (cfg?.giftList == null) return 0; var goldGift = cfg.giftList.Find(g => g != null && g.type == 1); return goldGift != null ? goldGift.count : 0; } /// 今日是否已签到 private bool IsSignedToday() { var sign = GameManager.Instance.user?.sign; return sign != null && sign.isSign; } private void UpdateBtnState() { btn_ChouJiang.interactable = !isSpinning && !IsSignedToday(); } private void OnChouJiangClick() { if (isSpinning) return; btn_ChouJiang.interactable = false; // SignIn 返回 SignRewardResult:day=本次签到天数,gold/diamond/product=本次奖励(服务端已含VIP加成) APIRequestList.SignIn(res => { if (res == null) { OnSignInDone(0); return; } int slot = SlotIndexByDay(res.day); if (slot < 0) { // day 匹配不到格子:不转转盘直接提示,避免停错位置 Debug.LogWarning($"[签到] 第{res.day}天在签到配置里匹配不到对应格子"); OnSignInDone(res.gold); return; } Debug.Log($"[签到] 第{res.day}天奖励{res.gold}金币 → 转盘格子{slot}"); RotateToSlot(slot, () => OnSignInDone(res.gold)); }); } /// 签到完成:提示奖励并刷新用户数据 private void OnSignInDone(long reward) { UIManager.Instance.ShowBoardError($"签到成功,获得{FormatGold(reward)}金币"); if (tmp_EndCoin != null) tmp_EndCoin.text = FormatGold(reward); APIRequestList.GetUser(user => { GameManager.Instance.UpdataUserData(user); UpdateBtnState(); }); } /// 按签到天数定位转盘格子:days按day升序后的下标;匹配不到返回-1 private int SlotIndexByDay(int day) { if (day_singConfig == null || day_singConfig.Count == 0 || SlotCount() == 0) return -1; var list = new List(day_singConfig.Values); list.Sort((a, b) => a.day - b.day); int count = Mathf.Min(list.Count, SlotCount()); for (int i = 0; i < count; i++) { if (list[i].day == day) return i; } return -1; } /// 单层转盘旋转停靠(参照SLZPDieEvent:LocalAxisAdd增量旋转+OutCubic缓动+完成强制校正) private void RotateToSlot(int slot, Action onComplete) { isSpinning = true; int cellCount = Mathf.Max(SlotCount(), 1); float targetAngle = slot * (360f / cellCount); float curr = zhuanPan.transform.localRotation.eulerAngles.z; float deltaToTarget = AngleDiff(curr, targetAngle, dir); float totalDelta = dir * spinRounds * 360f + deltaToTarget; Tween tween = zhuanPan.transform.DOLocalRotate(new Vector3(0, 0, totalDelta), rotateDuration, RotateMode.LocalAxisAdd); tween.SetEase(Ease.OutCubic); tween.OnComplete(() => { // 强制校正到精确目标角度,消除浮点误差 zhuanPan.transform.localRotation = Quaternion.Euler(0, 0, targetAngle); isSpinning = false; onComplete?.Invoke(); }); } /// 从curr到target的同向角度差(参照SLZPDieEvent.AngleDiff) private float AngleDiff(float curr, float target, float dir) { float diff = (target - curr) % 360f; if (diff < 0) diff += 360f; if (dir < 0 && diff > 0) diff -= 360f; return diff; } /// 金币数值格式化(万/亿单位) private static string FormatGold(long gold) { if (gold >= 100000000) // 亿 return $"{(gold / 100000000f):F1}亿"; if (gold >= 10000) // 万 return $"{(gold / 10000f):F1}万"; return gold.ToString("N0"); } }