201 lines
7.4 KiB
C#
201 lines
7.4 KiB
C#
using DG.Tweening;
|
||
using System.Collections;
|
||
using System.Collections.Generic;
|
||
using TMPro;
|
||
using UnityEngine;
|
||
using UnityEngine.UI;
|
||
|
||
public class BJEndUI : MonoBehaviour
|
||
{
|
||
public TextMeshProUGUI tMP_beishu;
|
||
public TextMeshProUGUI tMP_score;
|
||
public TMP_SpriteAsset goldSprite;
|
||
public TMP_SpriteAsset SilverSprite;
|
||
public Image img_BaoJiangZhong;
|
||
|
||
public bool useScoreAnim = false; // 是否启用分数递增动画
|
||
|
||
/// <summary>默认自动销毁延时(秒);not-self 在途状态会取消此计时,等 Finalize 后才重启</summary>
|
||
public float autoDestroyDelay = 5f;
|
||
|
||
[Header("Animator 状态机触发参数(not-self 流程)")]
|
||
[Tooltip("出现动画的 Trigger 参数名(ShowInProgress 入口触发)")]
|
||
public string animTrigger_Appear = "Appear";
|
||
[Tooltip("持续动画的 Trigger 参数名(ShowInProgress 出现动画完成后触发)")]
|
||
public string animTrigger_Loop = "Loop";
|
||
[Tooltip("关闭动画的 Trigger 参数名(Finalize 时触发,播完后销毁)")]
|
||
public string animTrigger_Close = "Close";
|
||
|
||
private Coroutine _destroyCo;
|
||
|
||
/// <summary>预制体自带的 Animator(出现/持续/关闭 三态由状态机控制)</summary>
|
||
private Animator _animator;
|
||
|
||
private void Awake()
|
||
{
|
||
_animator = GetComponent<Animator>();
|
||
if (autoDestroyDelay > 0)
|
||
_destroyCo = StartCoroutine(DestroyAfter(autoDestroyDelay));
|
||
}
|
||
|
||
private IEnumerator DestroyAfter(float delay)
|
||
{
|
||
yield return new WaitForSeconds(delay);
|
||
Destroy(gameObject);
|
||
}
|
||
|
||
/// <summary>取消当前自动销毁计时(用于 not-self 流程切换状态前)</summary>
|
||
public void CancelAutoDestroy()
|
||
{
|
||
if (_destroyCo != null)
|
||
{
|
||
StopCoroutine(_destroyCo);
|
||
_destroyCo = null;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 重置销毁计时并启动新的延时销毁。
|
||
/// </summary>
|
||
public void RestartAutoDestroy(float delay)
|
||
{
|
||
CancelAutoDestroy();
|
||
if (delay > 0)
|
||
_destroyCo = StartCoroutine(DestroyAfter(delay));
|
||
}
|
||
|
||
public void Init(int beishu, long score, bool isMine = false)
|
||
{
|
||
// 自己爆奖用金色精灵,别人用银色
|
||
tMP_beishu.spriteAsset = isMine ? goldSprite : SilverSprite;
|
||
tMP_score.spriteAsset = isMine ? goldSprite : SilverSprite;
|
||
|
||
tMP_beishu.text = "<sprite=6>"+ beishu.ToString();
|
||
|
||
if (useScoreAnim)
|
||
StartCoroutine(ScoreAnim(score));
|
||
else
|
||
tMP_score.text = score.ToString();
|
||
}
|
||
|
||
/// <summary>
|
||
/// not-self 爆奖进入"爆奖中"状态:
|
||
/// 关闭 tMP_beishu,激活 img_BaoJiangZhong,取消自动销毁(一直保持,直到收到 baoJiangEnd)。
|
||
/// 由 BaoJiangNotSelfHandler.ShowInProgress 调用。
|
||
/// 注意:此状态下 BJEndUI 不会自动消失,必须等 Finalize 才会显示倍率并启动销毁计时。
|
||
/// </summary>
|
||
public void ShowInProgress(bool isMine)
|
||
{
|
||
// 取消自动销毁:在途状态一直保持,直到收到 baoJiangEnd 帧同步走 Finalize
|
||
CancelAutoDestroy();
|
||
|
||
if (tMP_beishu != null) tMP_beishu.gameObject.SetActive(false);
|
||
if (tMP_score != null) tMP_score.gameObject.SetActive(false);
|
||
if (img_BaoJiangZhong != null) img_BaoJiangZhong.gameObject.SetActive(true);
|
||
|
||
// 预先应用金/银 spriteAsset,Finalize 时不用再切换
|
||
if (tMP_beishu != null) tMP_beishu.spriteAsset = isMine ? goldSprite : SilverSprite;
|
||
if (tMP_score != null) tMP_score.spriteAsset = isMine ? goldSprite : SilverSprite;
|
||
|
||
// ⭐ 触发 Animator 状态机:Appear(出现)→ Loop(持续,直到 Finalize)
|
||
// Animator 从 Appear 状态自然过渡到 Loop,由状态机配置控制时机
|
||
if (_animator != null)
|
||
{
|
||
if (!string.IsNullOrEmpty(animTrigger_Loop))
|
||
_animator.SetTrigger(animTrigger_Loop);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// not-self 收到帧同步 baoJiangEnd 后调用:
|
||
/// 1. 激活 tMP_beishu,关闭 img_BaoJiangZhong(必须)
|
||
/// 2. 触发 Close 动画状态机,播放分数递增1秒
|
||
/// 3. 等 Close 动画播完后销毁(缩小由 Animator 控制,不由代码 DOScale)
|
||
/// </summary>
|
||
public void Finalize(int beishu, long score, bool isMine)
|
||
{
|
||
CancelAutoDestroy();
|
||
|
||
// 步骤1:切换显示(必须)
|
||
if (tMP_beishu != null) tMP_beishu.gameObject.SetActive(true);
|
||
if (tMP_score != null) tMP_score.gameObject.SetActive(true);
|
||
if (img_BaoJiangZhong != null) img_BaoJiangZhong.gameObject.SetActive(false);
|
||
|
||
// 写入倍数 + 金银精灵
|
||
if (tMP_beishu != null)
|
||
{
|
||
tMP_beishu.spriteAsset = isMine ? goldSprite : SilverSprite;
|
||
tMP_beishu.text = "<sprite=6>" + beishu.ToString();
|
||
}
|
||
if (tMP_score != null)
|
||
{
|
||
tMP_score.spriteAsset = isMine ? goldSprite : SilverSprite;
|
||
}
|
||
|
||
// 步骤2+3:ScoreAnim 1秒递增 → 触发 Close 动画 → 等动画播完销毁
|
||
_destroyCo = StartCoroutine(FinalizeSequence(score));
|
||
}
|
||
|
||
/// <summary>
|
||
/// not-self 收尾序列:
|
||
/// 1. ScoreAnim 1秒递增(或等待1秒)
|
||
/// 2. 触发 Close 动画状态机(缩小由 Animator 控制)
|
||
/// 3. 等待动画播完后销毁(Animator 关闭动画结束时机由 Exit Time 或 AnimationEvent 决定,
|
||
/// 此处用动画长度作为兜底等待)
|
||
/// </summary>
|
||
private IEnumerator FinalizeSequence(long score)
|
||
{
|
||
// 等1秒(无论 useScoreAnim 是否开启,都要等1秒再触发 Close)
|
||
if (useScoreAnim && tMP_score != null)
|
||
{
|
||
yield return StartCoroutine(ScoreAnim(score));
|
||
}
|
||
else
|
||
{
|
||
if (tMP_score != null) tMP_score.text = score.ToString();
|
||
yield return new WaitForSeconds(1f);
|
||
}
|
||
|
||
// 触发 Close 动画状态机(缩小/淡出由 Animator 控制)
|
||
if (_animator != null && !string.IsNullOrEmpty(animTrigger_Close))
|
||
{
|
||
_animator.SetTrigger(animTrigger_Close);
|
||
|
||
// 等 Close 动画播完:优先用 AnimatorStateInfo.length,回退固定 0.5 秒
|
||
// 注意:Trigger 触发后需要等一帧让 Animator 切换状态,再读取 length
|
||
yield return null;
|
||
var stateInfo = _animator.GetCurrentAnimatorStateInfo(0);
|
||
float waitTime = stateInfo.length > 0 ? stateInfo.length : 0.5f;
|
||
yield return new WaitForSeconds(waitTime);
|
||
}
|
||
else
|
||
{
|
||
// 无 Animator:回退到 DOScale 缩小
|
||
yield return transform.DOScale(Vector3.zero, 0.3f).SetEase(Ease.InBack).WaitForCompletion();
|
||
}
|
||
|
||
Destroy(gameObject);
|
||
}
|
||
|
||
private IEnumerator ScoreAnim(long target)
|
||
{
|
||
float duration = 1f;
|
||
float elapsed = 0f;
|
||
tMP_score.text = "0";
|
||
|
||
// 放大
|
||
Vector3 normalScale = tMP_score.transform.localScale;
|
||
tMP_score.transform.DOScale(normalScale * 1.3f, duration * 0.3f).SetEase(Ease.OutBack);
|
||
|
||
while (elapsed < duration)
|
||
{
|
||
elapsed += Time.deltaTime;
|
||
tMP_score.text = ((long)(target * elapsed / duration)).ToString();
|
||
yield return null;
|
||
}
|
||
|
||
tMP_score.text = target.ToString();
|
||
tMP_score.transform.DOScale(normalScale, 0.15f).SetEase(Ease.InBack);
|
||
}
|
||
}
|