using System; using System.Collections; using System.Collections.Generic; using DG.Tweening; using Sirenix.OdinInspector; using UnityEngine; using UnityEngine.Events; using UnityEngine.Serialization; namespace Ichni.UI { public class UIPageBase : SerializedMonoBehaviour { public CanvasGroup mainCanvasGroup; public UnityAction fadeInStartAction; public UnityAction fadeInFinishAction; public UnityAction fadeOutAction; protected virtual void Awake() { CanvasGroup group = GetComponent(); if (group != null) { mainCanvasGroup ??= group; } } /// /// 显示页面并播放淡入动画。 /// 在 Canvas 已激活、保持完全透明且输入仍被阻断时执行, /// 适用于需要先完成视口定位、动态布局或数据绑定,再让玩家看见页面的场景。 /// public virtual void FadeIn(float duration = 0.5f, bool ignoreTimeScale = false, UnityAction action = null, UnityAction beforeFadeAction = null) { mainCanvasGroup.gameObject.SetActive(true); // 明确重置为不可见、不可交互状态,保证 beforeFadeAction 的任何布局变化都不会闪现在屏幕上。 mainCanvasGroup.alpha = 0f; mainCanvasGroup.interactable = false; mainCanvasGroup.blocksRaycasts = false; fadeInStartAction?.Invoke(); beforeFadeAction?.Invoke(); Tweener fade = mainCanvasGroup.DOFade(1f, duration).OnComplete(() => { mainCanvasGroup.interactable = true; mainCanvasGroup.blocksRaycasts = true; fadeInFinishAction?.Invoke(); action?.Invoke(); }); if (ignoreTimeScale) { fade.SetUpdate(true); } fade.Play(); } public virtual void FadeOut(float duration = 0.5f, bool ignoreTimeScale = false, UnityAction action = null) { mainCanvasGroup.interactable = false; mainCanvasGroup.blocksRaycasts = false; Tweener fade = mainCanvasGroup.DOFade(0f, duration).OnComplete(() => { fadeOutAction?.Invoke(); action?.Invoke(); mainCanvasGroup.gameObject.SetActive(false); }); if (ignoreTimeScale) { fade.SetUpdate(true); } fade.Play(); } } }