Files
5.24BuYu/Assets/MyGame/aa/UI/Home/Sub/UIHome_BY_UISignViewPanel.cs
T
2026-09-09 00:01:11 +08:00

233 lines
8.7 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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里面读取signConfigs后端配置的个数和text_CoinNums的个数是对应的 这里赋值的时候需要加上其他的数据公式是 值+值*GameManager的gameConfig的vip的signInAdd签到加成
/*签到API已封装在APIRequestList.SignIn(GET)
实测后端返回 {"data":440,"code":0,"info":null}——data直接是本次奖励的金币数字(不是SignInfo对象)
转盘停靠位置用奖励金额反查signConfigs得到(见FindSlotByReward)*/
//SLZPDieEvent这个脚本有之前写好的多层转盘的逻辑 签到这里只有单层 你可以直接看一下里面正确的
public List<Text> text_CoinNums;
public List<TextMeshProUGUI> text_CoinNums_TMP;
public TextMeshProUGUI tmp_VipJiaCheng; // 显示VIP签到加成百分比
public TextMeshProUGUI tmp_EndCoin; // 显示最终奖励金币数
public Button btn_ChouJiang;
public GameObject zhuanPan;
Dictionary<int, SignConfig> order_singConfig;
[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()
{
BuildOrderSignConfig();
UpdateSlotTexts();
UpdateBtnState();
UpdateVipAddText();
}
/// <summary>显示VIP签到加成百分比(signInAdd 0.15 → +15%)</summary>
private void UpdateVipAddText()
{
if (tmp_VipJiaCheng == null) return;
double add = GetSignInAdd();
tmp_VipJiaCheng.text = $"+{add * 100:0}%";
}
/// <summary>从GameManager的activityConfig读取signConfigs,按order建立字典</summary>
private void BuildOrderSignConfig()
{
order_singConfig = new Dictionary<int, SignConfig>();
var signConfigs = GameManager.Instance.activityConfig?.signConfigs;
if (signConfigs == null) return;
foreach (var cfg in signConfigs)
{
if (cfg == null) continue;
order_singConfig[cfg.order] = cfg;
}
}
/// <summary>当前用户的VIP签到加成(gameConfig.vipLevelConfigs按用户vipLevel匹配signInAdd)</summary>
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;
}
/// <summary>转盘格子数量:UGUI Text列表有绑定就用它,否则用TMP列表</summary>
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;
}
/// <summary>给第index个转盘格子设置文本(兼容UGUI Text与TMP)</summary>
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;
}
/// <summary>转盘格子赋值:值+值*signInAdd(VIP签到加成),按order排序后与text_CoinNums一一对应</summary>
private void UpdateSlotTexts()
{
int slotCount = SlotCount();
if (order_singConfig == null || order_singConfig.Count == 0 || slotCount == 0) return;
var list = new List<SignConfig>(order_singConfig.Values);
list.Sort((a, b) => a.order - b.order);
double add = GetSignInAdd();
int count = Mathf.Min(list.Count, slotCount);
for (int i = 0; i < count; i++)
{
long gold = list[i].gold;
long showGold = gold + (long)Math.Round(gold * add);
SetSlotText(i, FormatGold(showGold));
}
}
/// <summary>今日是否已签到</summary>
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的data直接返回本次奖励的金币数(数字)
APIRequestList.SignIn(reward =>
{
int slot = FindSlotByReward(reward);
if (slot < 0)
{
// 奖励金额匹配不到任何格子:不转转盘直接提示,避免停错位置
Debug.LogWarning($"[签到] 奖励{reward}在signConfigs里匹配不到对应格子");
OnSignInDone(reward);
return;
}
Debug.Log($"[签到] 奖励{reward} → 转盘格子{slot}");
RotateToSlot(slot, () => OnSignInDone(reward));
});
}
/// <summary>签到完成:提示奖励并刷新用户数据</summary>
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();
});
}
/// <summary>按奖励金额反查转盘格子:优先匹配加了VIP加成后的值,其次匹配原始配置值;匹配不到返回-1</summary>
private int FindSlotByReward(long reward)
{
if (order_singConfig == null || order_singConfig.Count == 0 || SlotCount() == 0) return -1;
var list = new List<SignConfig>(order_singConfig.Values);
list.Sort((a, b) => a.order - b.order);
double add = GetSignInAdd();
int count = Mathf.Min(list.Count, SlotCount());
int fallback = -1;
for (int i = 0; i < count; i++)
{
long gold = list[i].gold;
long withAdd = gold + (long)Math.Round(gold * add);
if (withAdd == reward) return i;
if (fallback < 0 && gold == reward) fallback = i;
}
return fallback;
}
/// <summary>单层转盘旋转停靠(参照SLZPDieEvent:LocalAxisAdd增量旋转+OutCubic缓动+完成强制校正)</summary>
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();
});
}
/// <summary>从curr到target的同向角度差(参照SLZPDieEvent.AngleDiff)</summary>
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;
}
/// <summary>金币数值格式化(万/亿单位)</summary>
private static string FormatGold(long gold)
{
if (gold >= 100000000) // 亿
return $"{(gold / 100000000f):F1}亿";
if (gold >= 10000) // 万
return $"{(gold / 10000f):F1}万";
return gold.ToString("N0");
}
}