UI显示隐藏框架

4 阅读2分钟

结构如下:

UIFramework
 ├── Core
 │   ├── UIManager.cs
 │   ├── UIRegistry.cs
 │   ├── UILayer.cs
 │   ├── UIType.cs
 │   ├── UIConfig.cs
 │   └── UIView.cs
 │
 ├── Runtime
 │   ├── UIRoot.cs
 │   └── UILoader.cs
 │
 └── Example
     └── InventoryUI.cs

下面是 完整代码版本(项目级可用)


一、UI 类型定义

public enum UIType
{
    None = 0,
    MainMenu,
    Inventory,
    Settings,
    Dialogue,
    Loading,
    Popup
}

二、UI 层级定义

大型项目必须有 UI 层级系统。

public enum UILayer
{
    Background,
    Normal,
    Popup,
    Top,
    Loading
}

三、UI 配置

控制 UI 的行为模式。

using UnityEngine;

[System.Serializable]
public class UIConfig
{
    public UIType uiType;
    public UILayer layer;

    public bool useStack = true;
    public bool allowMultiple = false;
}

四、UI 基类(核心)

所有 UI 继承这个。

using UnityEngine;
using DG.Tweening;
using Cysharp.Threading.Tasks;
using System.Threading;

[RequireComponent(typeof(CanvasGroup))]
public class UIView : MonoBehaviour
{
    public UIConfig config;

    protected CanvasGroup canvasGroup;
    protected RectTransform rectTransform;

    Tween tween;

    protected virtual void Awake()
    {
        canvasGroup = GetComponent<CanvasGroup>();
        rectTransform = GetComponent<RectTransform>();

        UIRegistry.Register(this);
    }

    protected virtual void OnDestroy()
    {
        UIRegistry.Unregister(this);
    }

    public virtual async UniTask ShowAsync(CancellationToken token = default)
    {
        gameObject.SetActive(true);

        canvasGroup.alpha = 0;

        tween?.Kill();

        tween = canvasGroup
            .DOFade(1, 0.25f)
            .SetEase(Ease.OutQuad);

        await tween.AsyncWaitForCompletion().AsUniTask().AttachExternalCancellation(token);
    }

    public virtual async UniTask HideAsync(CancellationToken token = default)
    {
        tween?.Kill();

        tween = canvasGroup
            .DOFade(0, 0.2f);

        await tween.AsyncWaitForCompletion().AsUniTask().AttachExternalCancellation(token);

        gameObject.SetActive(false);
    }
}

五、UI 注册系统

负责 UI 全局查找。

using System.Collections.Generic;

public static class UIRegistry
{
    static Dictionary<UIType, List<UIView>> uiMap = new();

    public static void Register(UIView view)
    {
        var type = view.config.uiType;

        if (!uiMap.ContainsKey(type))
            uiMap[type] = new List<UIView>();

        if (!uiMap[type].Contains(view))
            uiMap[type].Add(view);
    }

    public static void Unregister(UIView view)
    {
        var type = view.config.uiType;

        if (uiMap.ContainsKey(type))
            uiMap[type].Remove(view);
    }

    public static UIView Get(UIType type)
    {
        if (uiMap.TryGetValue(type, out var list))
        {
            if (list.Count > 0)
                return list[0];
        }

        return null;
    }
}

六、UI Root(层级管理)

这个对象建议场景里只有一个。

Canvas
 └── UIRoot
     ├── Background
     ├── Normal
     ├── Popup
     ├── Top
     └── Loading

脚本:

using UnityEngine;
using System.Collections.Generic;

public class UIRoot : MonoBehaviour
{
    public static UIRoot Instance;

    public Transform background;
    public Transform normal;
    public Transform popup;
    public Transform top;
    public Transform loading;

    Dictionary<UILayer, Transform> layerMap;

    void Awake()
    {
        Instance = this;

        layerMap = new Dictionary<UILayer, Transform>
        {
            { UILayer.Background, background },
            { UILayer.Normal, normal },
            { UILayer.Popup, popup },
            { UILayer.Top, top },
            { UILayer.Loading, loading }
        };
    }

    public Transform GetLayer(UILayer layer)
    {
        return layerMap[layer];
    }
}

七、UI 管理器(核心系统)

最重要的脚本。

using System.Collections.Generic;
using Cysharp.Threading.Tasks;
using System.Threading;
using UnityEngine;

public static class UIManager
{
    static Stack<UIView> uiStack = new();

    public static async UniTask<UIView> Show(UIType type, CancellationToken token = default)
    {
        var view = UIRegistry.Get(type);

        if (view == null)
        {
            Debug.LogError("UI 未注册: " + type);
            return null;
        }

        var layer = view.config.layer;
        view.transform.SetParent(UIRoot.Instance.GetLayer(layer), false);

        if (view.config.useStack)
            uiStack.Push(view);

        await view.ShowAsync(token);

        return view;
    }

    public static async UniTask Hide(UIType type)
    {
        var view = UIRegistry.Get(type);
        if (view == null) return;

        await view.HideAsync();
    }

    public static async UniTask HideTop()
    {
        if (uiStack.Count == 0) return;

        var view = uiStack.Pop();
        await view.HideAsync();
    }

    public static bool IsOpen(UIType type)
    {
        var view = UIRegistry.Get(type);
        if (view == null) return false;

        return view.gameObject.activeSelf;
    }
}

八、异步加载系统(支持 Addressables)

未来可以接资源系统。

using UnityEngine;
using Cysharp.Threading.Tasks;

public static class UILoader
{
    public static async UniTask<UIView> Load(string path)
    {
        var prefab = Resources.Load<GameObject>(path);
        var obj = GameObject.Instantiate(prefab);

        await UniTask.Yield();

        return obj.GetComponent<UIView>();
    }
}

可扩展成:

Addressables
AssetBundle
远程资源

九、示例 UI

例如背包界面:

using UnityEngine;

public class InventoryUI : UIView
{
    protected override void Awake()
    {
        base.Awake();
    }
}

配置:

UI Type: Inventory
Layer: Popup
Use Stack: true

十、调用方式(实际项目)

打开 UI

await UIManager.Show(UIType.Inventory);

关闭 UI

await UIManager.Hide(UIType.Inventory);

关闭最上层 UI

await UIManager.HideTop();

判断 UI 是否打开

UIManager.IsOpen(UIType.Inventory)

十一、生产级功能支持

这个框架已经支持:

✔ UI 自动注册
✔ UI 层级管理
✔ UI 栈
✔ 异步动画
✔ DOTween
✔ 多 UI 实例
✔ Addressables扩展
✔ VR UI


十二、如果是 VR 项目(推荐升级这个)

很多 VR 项目 UI 框架是这样扩展的:

UIRoot
 ├── ScreenSpaceUI
 ├── WorldSpaceUI
 ├── FollowUI
 ├── PopupUI

再加:

  • UI 跟随玩家
  • UI 自动面向相机
  • 交互锁
  • UI 阻挡检测

我可以帮你做一个 真正大型项目用的 UI Framework(很多公司内部用的那种) ,包括:

  • UI导航系统
  • UI历史记录
  • UI动画配置表
  • UI自动绑定
  • UI预加载系统

基本会变成一个 完整 Unity UI 架构