yyl
2025-07-29 b0a5d4688f1af73b5ad03ccc2df11c9aac1523a9
Main/System/UIBase/UIBase.cs
@@ -9,9 +9,9 @@
public enum UILayer
{
    Static, // 静态UI 适合做 战斗 主界面
    Bottom, // 主界面
    Mid,    // 功能窗口
    System,  // 网络弹窗/其他重要弹窗
    Bottom, // 部分界面特殊处理层级用
    Mid,    // 大部分功能窗口都放这层,便于跳转上下层管理(一个界面可以同时存在多个)
    System,  // 网络弹窗,信息提示等,其他重要弹窗
    Loading,    // 加载界面
}
@@ -25,7 +25,7 @@
    SlideFromBottom, // 从底部滑入
    SlideFromLeft, // 从左侧滑入
    SlideFromRight, // 从右侧滑入
    ScaleOverInOut,// 缩放(超过)之后再返回
    ScaleOverInOut,// 缩放根据曲线
}
@@ -40,7 +40,14 @@
    [SerializeField] public UILayer uiLayer = UILayer.Mid;
    [SerializeField][HideInInspector] public string uiName;
    [SerializeField] public bool isMainUI = false;
    [SerializeField] public bool supportParentChildRelation = true; // 新增:是否支持父子关系
    // 新增:是否支持父子关系
    // 父子关系:UI拥有的上下级链式关系
    // 在非特定情况下 都要拥有父子关系 (一般来说功能都要有父子关系 例外的是例如系统弹窗
    // 主界面这种不需要 在制作UI伤  目前的需求是 功能全部做在Middle层)
    // 拥有父子关系 在关闭父界面的时候 子界面会连同一起关闭 子界面打开时 父界面的“回合数”会刷新 回合数详见持久化相关的注释
    //
    [SerializeField] public bool supportParentChildRelation = true;
    // 持久化相关
    [SerializeField] public bool isPersistent = false;
@@ -49,7 +56,7 @@
    // 动画相关
    [SerializeField] public UIAnimationType openAnimationType = UIAnimationType.None;
    [SerializeField] public UIAnimationType closeAnimationType = UIAnimationType.None;
    [SerializeField] protected RectTransform _rectTransform; //界面默认添加根节点用于表现界面开启关闭动画
    [SerializeField] protected RectTransform _rectTransform; //界面默认添加根节点用于表现界面开启关闭动画,或者设置适配用
    
    [SerializeField]/*[HideInInspector]*/ public float animeDuration = 0.2f;
    [SerializeField]public TweenCurve scaleOverInOutCurve;
@@ -59,20 +66,19 @@
    [HideInInspector] public int lastUsedRound = 0;
    [HideInInspector] public UIBase parentUI;
    [HideInInspector] public GameObject rootNode; // 根节点
    // 子UI管理
    [HideInInspector] public List<UIBase> childrenUI = new List<UIBase>();
    //  打开遮罩
    [SerializeField] public bool openMask = false;
    //  点击空白区域关闭界面
    //  默认点击空白区域关闭界面
    [SerializeField] public bool clickEmptySpaceClose = false;
    private GameObject screenMask = null;
    private Button btnClickEmptyClose;
    public Action btnClickEmptyCloseEvent = null;   //提供点击空白区域关闭界面的回调
    //  跟OneLevelWin联动 实际上是需要继承自OneLevelWin才能生效的值 使用需要注意
    int m_FunctionOrder = 0;
@@ -111,7 +117,8 @@
        // 保存原始值用于动画
        if (_rectTransform != null)
        {
            originalPosition = _rectTransform.anchoredPosition;
            originalPosition = _rectTransform.anchoredPosition;;
        }
        ApplySettings();
@@ -137,12 +144,20 @@
            //延迟创建会导致层级在ScreenMask之上
            GameObject goBtnESC = GameObject.Instantiate(Resources.Load<GameObject>("Prefabs/ClickEmptyCloseMask"), transform);
            btnClickEmptyClose = goBtnESC.GetComponent<Button>();
            btnClickEmptyClose.AddListener(CloseWindow);
            btnClickEmptyClose.transform.SetAsFirstSibling();
            await UniTask.DelayFrame(5);
            btnClickEmptyClose = goBtnESC.GetComponent<Button>();
            btnClickEmptyClose.AddListener(CloseWindow);
            btnClickEmptyClose.AddListener(()=>
            {
                if (btnClickEmptyCloseEvent != null)
                {
                    btnClickEmptyCloseEvent();
                }
                else
                {
                    CloseWindow();
                }
            });
        }
    }
@@ -178,8 +193,9 @@
        // 设置Canvas属性
        canvas.overrideSorting = true;
        canvas.worldCamera = CameraManager.uiCamera;
        canvas.sortingLayerID = SortingLayer.NameToID("UI"); // 确保使用正确的排序层
        // 获取或添加CanvasGroup组件
        canvasGroup = GetComponent<CanvasGroup>();
@@ -228,6 +244,12 @@
    // 打开UI
    public void HandleOpen()
    {
        if (_rectTransform == null)
        {
            Debug.LogError($"界面: {uiName} 需要设置根节点_rectTransform ");
            return;
        }
        OnPreOpen();
        // 如果正在播放动画,先停止
        StopCurrentAnimation();
@@ -240,6 +262,10 @@
        // 根据动画类型播放打开动画
        PlayOpenAnimation();
        // // 如果后续需要统一处理刘海或者小游戏的界面适配问题
        // _rectTransform.offsetMin = new Vector2(0, 10);  //下方
        // _rectTransform.offsetMax = new Vector2(0, -50); //上方
        OnOpen();
@@ -327,24 +353,15 @@
    /// <summary>
    /// 播放UI特效
    /// </summary>
    /// <param name="effectName">特效资源名称</param>
    /// <param name="id">特效资源名称</param>
    /// <param name="parent">特效父节点,默认为当前UI</param>
    /// <param name="autoDestroy">是否自动销毁,默认为true</param>
    /// <param name="destroyDelay">自动销毁延迟时间,默认为5秒</param>
    /// <returns>特效游戏对象</returns>
    public EffectPlayer PlayUIEffect(int id, Transform parent = null, bool autoDestroy = true, float destroyDelay = 5f)
    public UIEffectPlayer PlayUIEffect(int id, Transform parent = null)
    {
        // 使用默认值
        if (parent == null) parent = transform;
        EffectPlayer player = parent.gameObject.AddComponent<EffectPlayer>();
        player.effectId = id;
        player.autoDestroy = autoDestroy;
        player.destroyDelay = destroyDelay;
        player.canvas = canvas;
        return player;
        return UIEffectPlayer.CreateEffect(id, parent, false);
    }
    
    #endregion
@@ -397,9 +414,9 @@
                    canvasGroup.alpha = 0f;
                    canvasGroup.blocksRaycasts = false;
                }
                if (canvasScaler != null)
                if (_rectTransform != null)
                {
                    canvasScaler.scaleFactor = 1f;
                    _rectTransform.localScale = Vector3.one;
                }
                break;
@@ -409,9 +426,9 @@
                    canvasGroup.alpha = 1f;
                    canvasGroup.blocksRaycasts = false;
                }
                if (canvasScaler != null)
                if (_rectTransform != null)
                {
                    canvasScaler.scaleFactor = 0.3f;
                    _rectTransform.localScale = Vector3.one * 0.3f;
                }
                break;
@@ -460,9 +477,9 @@
                    canvasGroup.alpha = 1f;
                    canvasGroup.blocksRaycasts = false;
                }
                if (canvasScaler != null)
                if (_rectTransform != null)
                {
                    canvasScaler.scaleFactor = 0.3f;
                    _rectTransform.localScale = Vector3.one * 0.3f;
                }
                break;
        }
@@ -485,7 +502,7 @@
                case UIAnimationType.ScaleInOut:
                    if (_rectTransform != null)
                    {
                        currentAnimation.Append(DOVirtual.Float(0.3f, 1f, animeDuration, (value) => {canvasScaler.scaleFactor = value;}).SetEase(animationEase));
                        currentAnimation.Append(DOVirtual.Float(0.3f, 1f, animeDuration, (value) => {_rectTransform.localScale = Vector3.one * value;}).SetEase(animationEase));
                    }
                    break;
@@ -501,19 +518,19 @@
                case UIAnimationType.ScaleOverInOut:
                    if (_rectTransform != null)
                    {
                        if (null == scaleOverInOutCurve)
                        {
                            currentAnimation.Append(DOVirtual.Float(0.3f, 1.2f, animeDuration,
                            (value) => {canvasScaler.scaleFactor = value;}).SetEase(animationEase));
                        }
                        else
                        {
                            currentAnimation.Append(DOVirtual.Float(0.3f, 1.2f, animeDuration,
                                (value) => {canvasScaler.scaleFactor = value;}).SetEase(scaleOverInOutCurve.curve));
                        }
                        float startScale = scaleOverInOutCurve.curve.Evaluate(0f);
                        _rectTransform.localScale = Vector3.one * startScale;
                        currentAnimation.Append(
                            DOTween.To(
                                () => _rectTransform.localScale.x,
                                (value) => _rectTransform.localScale = Vector3.one * value,
                                1f,
                                animeDuration
                            )
                            .SetEase(scaleOverInOutCurve.curve)
                            .OnComplete(() => _rectTransform.localScale = Vector3.one) // 确保最终值1正确
                        );
                        
                        // currentAnimation.Append(DOVirtual.Float(1.2f, 1f, 0.1f, (value) => {canvasScaler.scaleFactor = value;}).SetEase(scaleOverInOutCurve));
                    }
                    break;
            }
@@ -563,9 +580,9 @@
            canvasGroup.alpha = 1f;
            canvasGroup.blocksRaycasts = true;
        }
        if (canvasScaler != null)
        if (_rectTransform != null)
        {
            canvasScaler.scaleFactor = 1f;
            _rectTransform.localScale = Vector3.one;
        }
        if (_rectTransform != null)
@@ -609,7 +626,7 @@
                case UIAnimationType.ScaleOverInOut:
                    if (_rectTransform != null)
                    {
                        currentAnimation.Append(DOVirtual.Float(1f, 0.3f, animeDuration, (value) => {canvasScaler.scaleFactor = value;}).SetEase(animationEase));
                        currentAnimation.Append(DOVirtual.Float(1f, 0.3f, animeDuration, (value) => {_rectTransform.localScale = Vector3.one * value;}).SetEase(animationEase));
                    }
                    break;