中EN
概念页

UMG、Slate 与 Common UI

UMG, Slate & Common UI

更新于 2026-10-12 约 9 分钟UE5UIUMGSlateCommon UI

Slate 是 UE 平台无关的 C++ 声明式 UI 框架(编辑器即用它构建),UMG 是在其之上的可视化控件蓝图层(UE 5.8 API:UWidget 是所有暴露给 UObject 的被包装 Slate 控件的基类),Common UI 插件再在 UMG 之上补充多层界面、输入路由、手柄导航、平台按键图标和样式资产。官方 UMG 最佳实践强调事件驱动更新而非绑定/Tick、固定分辨率与 DPI 制作、用 Scale Box 而非 Render Transform 做永久缩放。

三层关系

层是什么谁用
Slate完全自定义、平台无关的 C++ UI 框架;编辑器本身就是用它写的,也可做游戏内 UI引擎/工具程序员
UMG (Unreal Motion Graphics)可视化 UI 编辑器与控件蓝图 (Widget Blueprint)设计师、UI 美术、玩法程序员
Common UI插件:在 UMG 之上提供多层 UI、输入路由、手柄导航与样式资产跨平台商业项目

Slate 的定位来自官方(Slate Overview);官方 UI 文档首页把 UMG 编辑器参考和「用 Slate 框架编程 UI」并列(UMG Best Practices / Creating User Interfaces)。UMG 控件是对 Slate 控件的 UObject 封装(UWidget 在运行时创建底层 SWidget)——UE 5.8 API 原文称 UWidget 是「所有暴露给 UObject 的被包装 Slate 控件的基类」,TakeWidget() 取得或构造底层 Slate 控件,各子类实现 RebuildWidget() 构造 SWidget,SynchronizeProperties() 把属性同步到原生控件(UWidget / CommonActivatableWidget / CommonActivatableWidgetStack API)。这一层关系解释了为什么 Widget Reflector(Slate 工具)能调试 UMG 界面。

Slate

  • 声明式语法:SLATE_BEGIN_ARGS、SLATE_ATTRIBUTE、SLATE_EVENT、SNew(...) 与 + SVerticalBox::Slot()[...] 嵌套组合。
  • 样式 (Styles):集中定义画刷、字体并复用。
  • 输入:鼠标键盘及可动态修改的按键绑定。输出:使用目标无关的渲染图元,通过 RHI 绘制,因此可跑在引擎支持的所有平台。
  • 布局图元、可停靠标签页框架、Widget Reflector 调试分析工具、直接访问引擎与编辑器。(以上 Slate Overview,官方页部分文字沿袭 UE4 表述)

UMG 实践(官方最佳实践)

  • 少量频繁变化的值可用属性绑定 (Property Binding);复杂界面应改用事件驱动更新,而不是每帧检查。
  • 以目标分辨率和 DPI Scale 1.0 制作所有控件蓝图,否则多分辨率缩放会不一致。
  • 纹理不要自带大量留白;把边框、角、背景拆开用 Border 模式平铺。
  • 槽位 Auto(按需)vs Fill(尽量占满)。
  • Render Transform 不参与布局,适合临时动画;永久缩放用 Scale Box。
  • 控件蓝图即 User Widget,可复用。
  • 优化:能用纹理就不用材质;用事件而非绑定或 Tick;缓存不常变的控件;用 Widget Reflector(Ctrl+Shift+W)查看统计。(以上 UMG Best Practices / Creating User Interfaces)

属性绑定每帧求值,本质是隐式 Tick,这与 委托与 Tick 机制 中「用委托/事件代替轮询」的原则一致(关联为通识);UI 的 CPU 开销可在 UE5 性能分析 中观察。

Common UI

官方定位:构建类似 Fortnite 的多层、跨平台 UI 的工具箱,包含:

  1. 一组提供常用游戏功能的 Common UI 控件;
  2. 把样式从 UI 元素中分离的样式数据资产;
  3. 输入路由 (Input Routing) 系统,让控件选择性可交互,便于管理多层 UI 的焦点;
  4. 平台专属元素(如对应手柄的按键图标);
  5. 手柄的方向导航 (Cardinal Navigation)。 另有与 增强输入 结合使用的专门文档。(Common UI)

可激活控件 (Activatable Widget):UCommonActivatableWidget 是可以在生命周期内被「激活/停用」而不必销毁或重建底层 SWidget 的控件基类。适用场景:界面需要开关但不想重建,需要内置「返回」行为(返回上一级、关闭弹窗),或者它是输入路由树上的一个节点。默认情况下它不会在构造时自动激活,也不接收返回操作;如果设为返回处理者 (Back Handler),收到返回时会停用但不销毁。关键属性:auto_activate、is_back_handler、is_modal(不论实际父级,都作为输入路由的根,用于模态弹窗屏蔽父级操作)、input_mapping(激活/停用时自动添加/移除增强输入映射上下文,见 增强输入)、auto_restore_focus;可重写 GetDesiredFocusTarget / GetDesiredInputConfig。注意:所有控件停用后,Common UI 不会自动恢复之前的输入配置。(UWidget / CommonActivatableWidget / CommonActivatableWidgetStack API,Python API 5.7)

控件栈:UCommonActivatableWidgetStack 只显示并激活栈顶控件,其余都停用;栈顶控件停用后自动移除,前一个控件重新显示并激活;RootContent 永不移除(Python API 5.4)。所以菜单层级通常用「推入栈 + 返回即停用」实现。Common UI Overview 概念页仍未能抓取;下面的输入路由和「层」来自 Epic 程序员 Nick Darnell 在 State of Unreal 2022 上的 Lyra 技术讲座(官方 YouTube 频道,UE 5.0 时期;Lyra Cross-platform UI Development (Nick Darnell, Epic Games) — Tech Talk, State of Unreal 2022)。

输入路由:Slate 输入从获得焦点的控件沿父级向上传递,最终到达视口 (Viewport),再经视口客户端交给玩家控制器。Common UI 要求项目把视口客户端换成 UCommonGameViewportClient 的子类,让输入先进入 UI 动作路由器 (CommonUIActionRouterBase,一个 LocalPlayer 子系统,见 子系统)。路由器决定是否触发已注册的 UI 动作,不处理的输入才继续传给玩家控制器。UI 动作(返回、应用、取消)定义在数据表里,分别映射手柄键和键盘键。

谁拿到输入:只有「最靠根的已激活控件」及其已激活的子控件会收到路由来的输入,Common UI 按绘制层级最高的可激活控件来判定。调试用 CommonUI.DumpActivatableTree。

层 (Layer):Common UI 只提供可激活控件和容器(栈与队列),不规定界面层级怎么组织;Lyra 自己在 CommonGame 插件中实现了一套(不属于引擎本体):

flowchart TD
  M["GameUIManagerSubsystem<br/>监听本地玩家加入/离开"] --> P["UI Policy(LyraUIPolicy)"]
  P --> L["每个玩家一个 PrimaryGameLayout"]
  L --> G["UI.Layer.Game 栈:HUD"]
  L --> GM["UI.Layer.GameMenu 栈:背包等游戏内菜单"]
  L --> MN["UI.Layer.Menu 栈:设置、主菜单"]
  L --> MD["UI.Layer.Modal 栈:确认弹窗"]

图中管理子系统通过 UI 策略为每个本地玩家创建一个主布局,布局里有四个用 Gameplay 标签注册的 CommonActivatableWidgetStack,从游戏 HUD 到模态弹窗,越往下层级越高。(讲座中层名为 Game / Game Menu / Menu / Modal;完整标签名 UI.Layer.* 来自 Lyra 工程,讲座原文只说「用 gameplay tag 注册」,标签写法参见 Gameplay 标签深入。)

要点与坑(均出自讲座):

  • 同一层里推入新控件会顶替当前控件,新控件停用后回到上一个,所以主菜单、设置、制作人员名单都放在 Menu 层,彼此替换。
  • 用 Add To Viewport 不维护层级,弹窗可能被 HUD 盖住,这正是需要层的原因。
  • 推入层时用软类引用并异步加载,否则硬引用会让一个界面把所有界面都拉进内存(见 资产管理与异步加载);加载期间暂停输入,防止玩家乱按误操作到下层界面。
  • 手柄断开提示这类必须常驻的界面不要放进栈里(可能被别的弹窗顶掉),应作为隐藏控件放在总布局中。
  • CommonHardwareVisibilityBorder 按平台特性和当前输入类型标签控制控件显隐(如 PC 才显示「退出游戏」)。

选型

需求建议
编辑器工具、细节面板定制Slate
一般游戏 HUD/菜单UMG
多层菜单 + 手柄/主机 + 按键提示UMG + Common UI
极致性能的自绘控件自定义 Slate 控件再包成 UMG(通识)

UI 管理器常写成 LocalPlayer 子系统,以便分屏时每个玩家一份(见 子系统,此为通识用法)。

  1. Slate Overview UE 5.8 文档
  2. UMG Best Practices / Creating User Interfaces UE 5.8 文档
  3. Common UI UE 5.8 文档
  4. UWidget / CommonActivatableWidget / CommonActivatableWidgetStack API UWidget UE 5.8 API;CommonActivatableWidget Python API 5.7;Stack Python API 5.4
  5. Lyra Cross-platform UI Development (Nick Darnell, Epic Games) — Tech Talk, State of Unreal 2022 Epic 官方 State of Unreal 2022 技术讲座(Lyra,UE 5.0 时期)

相关页面

游戏开发 · UE5增强输入Enhanced Input增强输入 (Enhanced Input) 是 UE5 默认启用的输入插件,把输入拆成四层:输入动作 (Input Action) 表示“玩家想做什么”,输入映射上下文 (Input Mapping Context) 规定“哪些按键在什么情境下触发它”,输入修饰器 (Input Modifier) 预处理原始值,输入触发器 (Input Trigger) 判定是否触发。上下文可在运行时按优先级增删,从而用数据资产而非代码处理情境切换、按键冲突与改键。游戏开发 · UE5蓝图与 C++ 协作Blueprint & C++ InteropEpic 官方建议:多数项目混用蓝图 (Blueprint) 与 C++,以 C++ 作为基础、在其上构建蓝图类。C++ 适合“编程”——定义系统;蓝图适合“脚本”——在已有系统上定义具体行为。两者通过反射说明符互相调用:C++ 用 BlueprintCallable/BlueprintReadWrite 等暴露给蓝图,用 BlueprintImplementableEvent/BlueprintNativeEvent 让蓝图实现或覆盖 C++ 声明的函数。游戏开发 · UE5UE5 性能分析UE5 ProfilingUE5 性能分析的基本流程是:先用 stat unit 判断瓶颈在游戏线程、渲染线程还是 GPU,再用对应的 stat 组、profilegpu/GPU 统计或 Unreal Insights 的 Timing/Memory 等视图向下钻取;渲染特性(RDG、VSM、TSR)各自提供作用域和可视化。测量时要避开会扭曲数据的设置(调试构建、异步计算、可视化模式)。游戏开发 · UE5子系统Subsystems子系统 (Subsystem) 是自动实例化、生命周期绑定在宿主对象上的类:Engine、Editor、GameInstance、World、LocalPlayer 五种。宿主创建时自动创建并 Initialize(),宿主关闭时 Deinitialize(),之后无引用即被 GC。它替代了「继承 GameInstance 塞管理器」的老做法,自带按类型的蓝图节点和 Python 访问,特别适合插件。官方编程页只列四种,World 子系统依据 5.8 Python API 补充。游戏开发 · UE5Game Features 与模块化玩法Game Features & Modular GameplayGame Features 与 Modular Gameplay 两个插件让开发者把一个玩法功能做成独立的插件,可以单独启用或停用。功能本身由一个 GameFeatureData 资产里的 Action 列表描述,最常用的是 Add Components:把插件里的组件按需挂到已有的 Actor 类上。这样主工程的代码保持干净,无关功能之间不会意外产生依赖,对需要长期增减功能的线上产品尤其重要。游戏开发 · UE5编辑器扩展与 Python 脚本Editor Extension & Python Scripting扩展 UE 编辑器有三条主要路线,门槛由低到高:Python 脚本(只在编辑器中可用,适合批量处理资产和串联外部 DCC 管线)、Editor Utility Widget(基于 UMG 的蓝图编辑器界面,做成自定义标签页),以及 C++ 编辑器插件(如 Editor Standalone Window 模板,用 Slate 的声明式语法构建窗口)。游戏开发 · UE5智能指针与 TObjectPtrSmart Pointers & TObjectPtrUE 有两套对象寿命管理:普通 C++ 对象用引用计数智能指针(TSharedPtr/TSharedRef/TWeakPtr/TUniquePtr),UObject 由垃圾回收管理,不能放进这些智能指针。UE5 新增的 TObjectPtr 用来替代 UPROPERTY 里的 UObject 裸指针:编辑器构建中提供动态解析和访问跟踪,非编辑器构建中与裸指针表现相同。游戏开发 · UE5本地化LocalizationUE 的本地化以 FText 类型为中心,国际化(数字、日期、复数规则、文化回退)依赖 ICU 库。可本地化的文本由命名空间、键、源字符串三部分标识;本地化管线按目标 (Localization Target) 依次收集 (Gather) 到 manifest、翻译进各文化的 archive(通常经 PO 文件导出导入)、编译成运行时加载的 .locres。Localization Dashboard 是管理这条管线的推荐工具。图形学覆盖层与用户界面渲染Overlays & User Interface RenderingHUD、武器选择界面、各种菜单等图形用户界面,加上调试绘制,都在主 3D 场景渲染完之后才画,所以统称覆盖层 (overlay)。它们一般关闭深度测试、用屏幕空间四边形和正交投影绘制,由文字、位图、嵌入视频和矢量图形几类二维图元组成(GEA4 卷 II 12.8)。游戏策划游戏界面Game Interface界面是分隔玩家(阳)与游戏(阴)那层无限薄的膜;界面失灵,体验之火即熄。界面的目标不是好看或流畅,而是让玩家感到掌控自己的体验。Schell 把界面拆成物理输入、物理输出、虚拟界面三部分和其间的六种映射 (mapping),并讨论透明、反馈、多汁 (juiciness)、原始性 (primality)、信息通道与维度、界面模式,以及十条实用建议(第 3 版第 15 章 Players Play Games through an Interface;第 1 版为第 13 章,无原始性一节,建议为八条)。游戏开发 · UE5Gameplay 标签深入Gameplay Tags In DepthGameplay 标签 (Gameplay Tags) 是用 . 分层的用户定义标签,必须登记到标签字典(项目设置 .ini、数据表或 C++ 原生标签宏)。对象用 FGameplayTagContainer 持有多个标签并以 HasTag/HasAny/HasAll 判断(注意空集合语义),复杂条件用 FGameplayTagQuery 的叶/根表达式组合并配置在资产里。它是 GAS、AI 和各类玩法状态的通用词汇表;大项目可限制标签编辑权限,并用 IGameplayTagAssetInterface 免 Cast 取标签。游戏开发 · UE5委托与 Tick 机制Delegates & TickUE 有两种驱动游戏逻辑的方式:事件驱动——委托 (Delegate) 在某事发生时回调绑定的函数;轮询驱动——Tick 每帧(或按最小间隔)调用 Actor/组件的更新函数,并按 Tick 组 (Tick Group) 与物理模拟排序。官方建议能用定时器、委托就不用 Tick,必须 Tick 时用 Tick 组和 Tick 依赖保证顺序,避免“差一帧”问题。游戏开发 · UE5资产管理与异步加载Asset Management & Async LoadingUE 资产默认按引用自动加载:硬引用 (Hard Reference) 会让被引用资产随引用者一起加载,不加控制就可能在启动时加载全部内容。软引用 (Soft Reference,TSoftObjectPtr/FSoftObjectPath) 只存路径,配合流式管理器 (Streamable Manager) 异步按需加载;资产管理器 (Asset Manager) 进一步把内容划分为主资产 (Primary Asset) 和次资产 (Secondary Asset),用资产包 (Asset Bundle) 管理加载、卸载、烘焙分块与内存审计。

输入关键词开始搜索

滚轮或双指缩放 · 拖动平移 · 双击放大 / 还原