Files
Cielonos/Assets/Scripts/Core/UI/ScreenFader.cs

103 lines
3.4 KiB
C#
Raw Normal View History

2026-02-13 09:22:11 -05:00
using System;
using DG.Tweening; // 引入 DOTween
using UnityEngine;
using SLSUtilities.UI;
namespace Cielonos.Core.UI
{
// 继承 UIElementBase同时实现简单的单例逻辑
public class ScreenFader : UIElementBase
{
public static ScreenFader Instance { get; private set; }
[Header("Settings")]
[SerializeField] private float defaultDuration = 0.5f;
[SerializeField] private bool startBlack = true;
[SerializeField] private Ease fadeEase = Ease.InOutQuad; // 暴露曲线设置,比 SmoothStep 更灵活
private Tween currentTween; // 记录当前动画,防止冲突
private void Awake()
{
// --- 单例逻辑 ---
if (Instance != null && Instance != this)
{
Destroy(gameObject);
return;
}
Instance = this;
// ----------------
// 初始化状态
if (canvasGroup == null) canvasGroup = GetComponent<CanvasGroup>();
if (startBlack)
{
canvasGroup.alpha = 1f;
canvasGroup.blocksRaycasts = true;
}
else
{
canvasGroup.alpha = 0f;
canvasGroup.blocksRaycasts = false;
}
}
private void OnDestroy()
{
// 这是一个好习惯:销毁时杀掉所有未完成的动画,防止报错
currentTween?.Kill();
}
/// <summary>
/// 变黑 (Fade Out / 遮挡屏幕)
/// </summary>
public Tween FadeToBlack(float duration = -1, Action onComplete = null)
{
return FadeTo(1f, duration, onComplete);
}
/// <summary>
/// 变亮 (Fade In / 显示屏幕)
/// </summary>
public Tween FadeToClear(float duration = -1, float delay = 1, Action onComplete = null)
{
return FadeTo(0f, duration, onComplete).SetDelay(delay);
}
/// <summary>
/// 通用淡入淡出逻辑
/// 返回 Tween 对象,允许外部使用 yield return tween.WaitForCompletion();
/// </summary>
private Tween FadeTo(float targetAlpha, float duration, Action onComplete)
{
// 1. 如果有正在运行的动画,立刻杀掉,确保从当前 alpha 开始新的变化
currentTween?.Kill();
float d = duration < 0 ? defaultDuration : duration;
// 2. 只有在变黑alpha -> 1开始时才阻挡射线
// 这样防止玩家在变黑过程中还能点击后面的按钮
if (targetAlpha > 0.5f)
{
canvasGroup.blocksRaycasts = true;
}
// 3. 使用 DOTween
currentTween = canvasGroup.DOFade(targetAlpha, d)
.SetEase(fadeEase)
.SetUpdate(true) // 【关键】忽略 TimeScale游戏暂停时依然可以淡入淡出
.OnComplete(() =>
{
// 只有在完全变亮alpha -> 0结束后才取消阻挡
if (targetAlpha < 0.01f)
{
canvasGroup.blocksRaycasts = false;
}
onComplete?.Invoke();
});
return currentTween;
}
}
}