结构如下:
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 架构。