using UnityEngine; using DG.Tweening; using System.Collections.Generic; public class HeroDebutCallResultWin : UIBase { [SerializeField] Transform moneyRect; [SerializeField] OwnItemCell ownItemCell; [SerializeField] ItemCell presentItemCell; // 抽卡获得的赠送道具 [SerializeField] RectTransform oneRect; // 单抽容器中心点 [SerializeField] HeroDebutCallResultCell oneCell; // 单抽单元格 [SerializeField] RectTransform tenRect; // 十连容器 [SerializeField] HeroDebutCallResultCell[] tenCell; // 十连单元格数组 [SerializeField] UIEffectPlayer firstEffect; // 开屏初始特效 [SerializeField] HeroDebutCallButton callButton; // 再次抽取按钮 [SerializeField] ButtonEx okButton; // 确定返回按钮 HeroDebutManager manager => HeroDebutManager.Instance; HappyXBModel xbManager => HappyXBModel.Instance; bool isSkip; // 是否跳过动画 int treasureType; // 抽卡宝库类型 bool isOne = false; // 是否为单抽模式 private Sequence animSeq; // 主动画序列 protected override void InitComponent() { okButton.SetListener(CloseWindow); } protected override void OnPreOpen() { animSeq?.Kill(); var act = manager.GetOperationHeroAppearInfo(); if (act == null) return; var config = ActHeroAppearConfig.Get(act.CfgID); if (config == null) return; treasureType = config.ActTreasureType; // 根据配置和时间戳加载用户的是否跳过动画设置 isSkip = manager.LoadCallSkipData(config.CfgID, act.startDate, act.endDate); // 绑定数据刷新回调 HappyXBModel.Instance.RefreshXBResultAct += RefreshXBResultAct; HappyXBModel.Instance.RefreshXBTypeInfoAct += OnRefreshXBTypeInfoAct; var treasureSetConfig = TreasureSetConfig.Get(config.ActTreasureType); if (treasureSetConfig == null) return; ownItemCell.itemID = treasureSetConfig.CostItemID; RefreshXBResultAct(); } protected override void OnPreClose() { animSeq?.Kill(); // 解绑回调,防止内存泄漏 HappyXBModel.Instance.RefreshXBResultAct -= RefreshXBResultAct; HappyXBModel.Instance.RefreshXBTypeInfoAct -= OnRefreshXBTypeInfoAct; } /// /// 刷新抽卡结果界面 /// void RefreshXBResultAct() { isOne = HeroUIManager.Instance.selectCallIndex == 0; // 初始化顶部赠送物品 int itemId = xbManager.addXBAddItemID; long count = xbManager.addXBItemCount; presentItemCell.Init(new ItemCellModel(itemId, true, count)); presentItemCell.button.SetListener(() => ItemTipUtility.Show(itemId)); // 根据单抽或十连填充物品数据 if (isOne) { if (!xbManager.xbResultDict.IsNullOrEmpty()) { oneCell.DisplayItemCell(xbManager.xbResultDict[0].itemId, xbManager.xbResultDict[0].count); } } else { for (int i = 0; i < tenCell.Length; i++) { if (i < xbManager.xbResultDict?.Count) { tenCell[i].DisplayItemCell(xbManager.xbResultDict[i].itemId, xbManager.xbResultDict[i].count); } } } callButton.Display(treasureType, HeroUIManager.Instance.selectCallIndex); if (isSkip) { // 模式:跳过动画,直接显示最终状态 firstEffect.SetActive(false); ShowImmediate(); } else { // 模式:播放完整展示动画 PrepareAnimation(); firstEffect.SetActive(true); firstEffect.Play(0); // 预留 1.1s 的开屏动效时间后,开始播放发牌/翻牌序列 PlayResultAnimation(1.1f); } } private void OnRefreshXBTypeInfoAct() { RefreshXBResultAct(); } /// /// 静态显示(无动画直接展示结果) /// private void ShowImmediate() { animSeq?.Kill(); oneRect.SetActive(isOne); tenRect.SetActive(!isOne); ownItemCell.SetActive(true); moneyRect.SetActive(true); presentItemCell.SetActive(true); callButton.SetActive(true); okButton.SetActive(true); if (isOne) { oneCell.SetActive(true); oneCell.ResetState(); oneCell.itemCell.SetActive(true); } else { for (int i = 0; i < tenCell.Length; i++) { if (i < xbManager.xbResultDict?.Count) { tenCell[i].SetActive(true); tenCell[i].transform.localPosition = tenCell[i].originalLocalPos; tenCell[i].ResetState(); tenCell[i].itemCell.SetActive(true); } else { tenCell[i].SetActive(false); } } } } /// /// 动画前置准备(隐藏元素并重置坐标) /// private void PrepareAnimation() { oneRect.SetActive(isOne); tenRect.SetActive(!isOne); ownItemCell.SetActive(false); moneyRect.SetActive(false); presentItemCell.SetActive(false); callButton.SetActive(false); okButton.SetActive(false); if (isOne) { oneCell.SetActive(true); oneCell.ResetState(); } else { for (int i = 0; i < tenCell.Length; i++) { if (i < xbManager.xbResultDict?.Count) { tenCell[i].SetActive(true); tenCell[i].ResetState(); tenCell[i].transform.localPosition = tenCell[i].originalLocalPos; } else { tenCell[i].SetActive(false); } } } } /// /// 核心逻辑:编排结果展示动画时间轴 /// private void PlayResultAnimation(float startDelay = 0f) { animSeq?.Kill(); animSeq = DOTween.Sequence(); if (isOne) { // ==================== 单抽动画逻辑 ==================== float timelineCursor = startDelay; // 1. 播放中心光团 animSeq.InsertCallback(timelineCursor, () => oneCell.PlayInitialOrb()); // 预留短暂的展示时间 float finishShowTime = 0.12f; timelineCursor += finishShowTime; // 2. 触发爆开与翻牌组合动画 int itemId = xbManager.xbResultDict[0].itemId; int quality = GetOrbQuality(itemId); int flowQuality = GetFlowQuality(itemId); animSeq.Insert(timelineCursor, oneCell.PlayExplosionFadeAndFlipReveal(quality, flowQuality)); // 推进游标至组合动画结束(1.1s基础时长 + 0.3s缓冲) timelineCursor += 1.4f; // 3. 弹出底部 UI animSeq.InsertCallback(timelineCursor, ShowBottomUI); } else { // ==================== 十连动画逻辑 ==================== int count = xbManager.xbResultDict.Count; float staggerInterval = 0.1f; // 发牌间隔 float moveDuration = 0.12f; // 飞行时间 float timelineCursor = startDelay; // 1. 依次从中心点向目标位置发射光团(发牌阶段) for (int i = 0; i < count; i++) { var cell = tenCell[i]; cell.transform.position = oneRect.position; // 起始于中心 float delay = timelineCursor + i * staggerInterval; animSeq.InsertCallback(delay, () => cell.PlayInitialOrb()); animSeq.Insert(delay, cell.transform.DOLocalMove(cell.originalLocalPos, moveDuration).SetEase(Ease.OutCubic)); } // 计算所有卡牌完成飞行的时刻 float finishFlyingTime = ((count - 1) * staggerInterval) + moveDuration; timelineCursor += finishFlyingTime; // 2. 依次触发爆开翻牌动画(展示阶段) for (int i = 0; i < count; i++) { int itemId = xbManager.xbResultDict[i].itemId; int quality = GetOrbQuality(itemId); int flowQuality = GetFlowQuality(itemId); animSeq.Insert(timelineCursor + i * staggerInterval, tenCell[i].PlayExplosionFadeAndFlipReveal(quality, flowQuality)); } // 计算全部卡牌翻转完成的时间点并加入缓冲 float finalFlipDuration = 1.1f + ((count - 1) * staggerInterval) + 0.3f; timelineCursor += finalFlipDuration; // 3. 弹出底部 UI animSeq.InsertCallback(timelineCursor, ShowBottomUI); } } /// /// 展示底部操作按钮,并检查是否触发武将立绘 /// private void ShowBottomUI() { ownItemCell.SetActive(true); moneyRect.SetActive(true); presentItemCell.SetActive(true); callButton.SetActive(true); okButton.SetActive(true); presentItemCell.transform.localScale = Vector3.zero; callButton.transform.localScale = Vector3.zero; okButton.transform.localScale = Vector3.zero; Sequence bottomSeq = DOTween.Sequence(); bottomSeq.Append(presentItemCell.transform.DOScale(Vector3.one, 0.3f).SetEase(Ease.OutBack)); bottomSeq.Join(callButton.transform.DOScale(Vector3.one, 0.3f).SetEase(Ease.OutBack)); bottomSeq.Join(okButton.transform.DOScale(Vector3.one, 0.3f).SetEase(Ease.OutBack)); bottomSeq.OnComplete(() => { if (!isSkip) { CheckAndShowHeroLH(); } }); animSeq.Append(bottomSeq); } /// /// 检测并展示高品质武将立绘(弹窗展示) /// private void CheckAndShowHeroLH() { // 清理缓存列表 ItemLogicUtility.Instance.poplhHeroIdList.Clear(); List uniqueHeroIds = new List(); int count = xbManager.xbResultDict.Count; for (int i = 0; i < count; i++) { int itemId = xbManager.xbResultDict[i].itemId; // 仅对 HeroConfig 中存在的完整武将进行处理 if (HeroConfig.HasKey(itemId)) { // 仅展示高于设定品质的武将 if (HeroConfig.Get(itemId).Quality < HappyXBModel.Instance.lhQuality) continue; if (!uniqueHeroIds.Contains(itemId)) { uniqueHeroIds.Add(itemId); } } } // 如果存在符合条件的武将,打开大图展示界面 if (uniqueHeroIds.Count > 0) { ItemLogicUtility.Instance.poplhHeroIdList = uniqueHeroIds; if (!UIManager.Instance.IsOpenedInList()) { UIManager.Instance.OpenWindow(); } } } // --- 辅助方法:映射配置品质到特效索引 --- private int GetOrbQuality(int itemId) { int qualityLevel = ItemConfig.Get(itemId).ItemColor; switch (qualityLevel) { case 2: return 5; // 紫色 case 3: return 2; // 黄色 case 4: return 0; // 橙色 case 5: return 1; // 红色 default: return 0; } } private int GetFlowQuality(int itemId) { int qualityLevel = ItemConfig.Get(itemId).ItemColor; switch (qualityLevel) { case 2: return 3; // 紫色 case 3: return 2; // 黄色 case 4: return 0; // 橙色 case 5: return 1; // 红色 default: return 0; } } }