UMG
前言
Unreal Engine重要概念 - UMG(Unreal Motion Graphics)
Unreal Engine重要概念 - UMG(Unreal Motion Graphics) - 知乎
基本信息
1. 控件(Widgets)
控件是 UI 的基本单位,就像拼积木一样:
| 控件名称 | 说明 | 常见用途 |
|---|---|---|
| Text | 显示一段文字 | 显示血量、任务说明、名字等 |
| Image | 显示图片或图标 | 技能图标、头像、背景等 |
| Progress Bar | 进度条,可以用来显示某个数值变化的条 | 血条、经验条、技能冷却条 |
| Button | 可以点击的按钮 | 菜单选项、对话选项 |
| Canvas Panel | 允许你自由定位其他控件 | 通常用于主界面、HUD 布局 |
| Vertical Box / Horizontal Box | 用来垂直/水平排列控件 | 对话选项、物品列表、任务列表 |
| Overlay | 控件层叠显示(上下叠加) | 技能图标 + 冷却进度 + 数量 |
2. 层级结构(控件树)
UMG 的界面是“树形结构”的,最外层是容器(比如 Canvas Panel),内部再嵌套各种控件。
比如一个任务提示 UI:
- Canvas Panel(整体布局)
- Border(背景框)
- Text(任务内容)
- Text(进度百分比)
- Border(背景框)
这种结构就像网页的 HTML 一样,嵌套使用。
3. 绑定数据 & 交互逻辑
UMG 不只是静态画面,它能与游戏里的数据互动,比如:
- 显示玩家当前生命值
- 点击按钮进入下一关
- 显示背包中有哪些物品
- 玩家进入新区域后显示提示
通过 数据绑定,UMG 会实时显示游戏里的状态变化。
主要控件
🧩 UMG核心控件分类
一、面板控件(Panel Widgets)
| 控件名称 | 功能描述 | 关键特性 |
|---|---|---|
| Canvas Panel | 自由布局容器 | ✅ 支持锚点(Anchors)和绝对定位 ✅ 动态适配不同分辨率 |
| Grid Panel | 表格布局容器 | 🔳 行/列自动分割 🔄 子控件可跨行/列合并 |
| Horizontal Box | 水平排列容器 | ➡️ 自动横向排列子控件 📏 支持Size to Content(自适应内容尺寸) |
| Vertical Box | 垂直排列容器 | ⬇️ 自动纵向排列子控件 ⚖️ 支持比例填充(填满剩余空间) |
| Overlay | 层叠容器 | 📚 支持多层控件叠加 🔼 通过Z-Order控制显示层级 |
| Safe Zone | 异形屏适配容器 | 📱 自动避开刘海/挖孔区域 🛡️ 支持四向独立安全区设置 |
二、输入控件(Input Widgets)
| 控件名称 | 类型 | 交互特性 |
|---|---|---|
| Button | 基础按钮 | 🔘 四态样式(Normal/Hovered/Pressed/Disabled) 🔗 点击事件绑定 |
| ComboBox(String) | 下拉选择框 | 📋 文本选项列表 ⌨️ 支持键盘快速选择 |
| Editable Text | 单行输入框 | ✏️ 实时文本编辑 🚫 自带输入校验基础功能 |
| Editable Text(Multi-Line) | 多行输入框 | ↵ 支持回车换行 📄 大段文本输入优化 |
| Slider | 滑动条 | 🎚️ 线性值调节(0.0-1.0) 📈 支持步进(Step)设置 |
| Spin Box | 数字调节框 | 🔢 精确数值输入 ➕➖ 附带增减按钮 |
三、通用控件(Common Widgets)
| 控件名称 | 渲染能力 |
|---|---|
| Image | 🖼️ 支持纹理/材质/纯色块 🎨 九宫拉伸(Box Hospitality) + 染色(Tint) |
| Text Block | 🔤 静态文本渲染 ⚠️ 不支持富文本(需第三方插件) |
| Rich Text Block | ✨ 富文本渲染 ✅ 混合样式/内嵌图片/超链接 |
| Progress Bar | ████████ 进度可视化 🌀 支持Marquee模式(无进度值的滚动动画) |
| Border | 🟦 容器装饰控件 🎯 定义背景+边距+边框样式 |
四、高级功能控件
| 控件名称 | 核心用途 |
|---|---|
| Widget Switcher | 🔀 多页面切换器 💡 实现选项卡(Tab)界面 |
| Retainer Box | ⚡ 渲染性能优化 📉 降低动画更新频率(如每秒10帧而非60帧) |
| Named Slot | 🧩 预留插入点 🚀 运行时动态加载子控件 |
| Radial Slider | 🎡 圆形滑块 ⭕ 旋转角度输入(适用方向盘/罗盘UI) |
五、开发者工具
| 功能 | 操作路径 |
|---|---|
| 创建自定义控件 | 右键 → User Interface → Widget Blueprint |
| 控件嵌套 | 将控件蓝图拖入其他UMG画布 |
| 动态控件生成 | 使用Create Widget+AddChild节点 |
⚙️ 性能优化专项控件
1 | graph TD |
8.13
TimeLine动画
【虚幻5UI进阶教程】如何制作UI动画哔哩哔哩bilibili
创建WBP –> 窗口 –>动画
这边动画类似timeline
这边能k的动画 有: visibility(可见度) Cursor(锚点)Transform(位移)Scale(缩放)
k动画: 关键帧在timeline上回车键
- 蓝图节点PlayAnimation
- Target – 默认self
- In Animation 动画
- Start at Time 开始time
- Num Loops to Play 是否Loop
- Play Mode Forward–快进(从前往后) Reverse–翻转(从后往前) PingPong–乒乓(从前往后+从后往前)
- Playback Speed 播放速率
- Restore State bool (动画停止时将控件恢复到动画预设置状态?不重要)
- return UMGSequence Player UMG播放器
UMG与Slate
Unreal Motion Graphics(UMG)是虚幻引擎中用于创建用户界面的高级框架,但其底层实现依赖于Slate框架和渲染管线优化技术。以下是UMG底层的核心机制解析:
🔧 1. 核心架构:UMG与Slate的关系
- UMG是Slate的封装:UMG基于Slate框架构建,通过组合(Composition)而非继承(Inheritance)实现对Slate控件的封装。每个UMG控件(如
UButton、UTextBlock)内部包含对应的Slate控件(如SButton、STextBlock)3,5。 - 类命名规范:
- UMG控件:以
U开头(如UWidget),继承自UObject,支持蓝图编辑和垃圾回收。 - Slate控件:以
S开头(如SWidget),直接处理布局、渲染和输入事件,不依赖蓝图系统3,5。
- UMG控件:以
- 设计目标:UMG提供可视化编辑器,降低UI开发门槛;Slate则提供高性能、跨平台的底层支持,用于编辑器界面和复杂控件3。
🎨 2. 渲染管线:从控件到GPU指令
UMG的渲染分为三个阶段,最终生成GPU可处理的渲染批次:
| 阶段 | 关键数据结构 | 功能 | 性能影响 |
|---|---|---|---|
| 1. 生成绘制元素 | FSlateDrawElement | 存储控件的绝对空间信息(位置、尺寸、裁剪区域)和渲染数据 | 控件复杂度影响生成开销 |
| 2. 创建渲染批次 | FSlateRenderBatch | 将FSlateDrawElement转换为顶点/索引数据,准备GPU指令 | 纹理切换和材质复杂度是关键瓶颈 |
| 3. 合批优化 | FSlateRenderBatch合并 | 合并相同材质/纹理的批次,减少Draw Call | 显著提升渲染效率3 |
- 控件遍历流程:采用深度优先递归遍历,父控件(如
UCanvasPanel)先处理布局信息,子控件生成FSlateDrawElement时继承父级变换3。 - 动态数据处理:通过
FSlateDataPayload子类(如FSlateTextPayload)存储控件专属数据(如文本内容),避免内存浪费3。
⚡ 3. 事件处理与数据绑定
- 事件驱动机制:
- 数据绑定原理:
⚙️ 4. 性能优化技术
- 全局无效化(GlobalInvalidation):
- 原理:缓存未变化的
FSlateDrawElement,仅重新生成修改过的控件数据,减少CPU计算量。 - 限制:仅在非编辑器环境(如打包后进程)生效3。
- 原理:缓存未变化的
- 合批优化:
- 合并相同材质的渲染批次,降低Draw Call。
- 避免频繁切换纹理或材质状态3。
- 控件裁剪与折叠:
- 设置
Visibility为Collapsed而非Hidden,完全移除控件布局计算1,3。
- 设置
🚀 5. 高级特性与扩展
- 自定义Slate控件:
- 直接继承
SWidget实现高性能控件(如编辑器工具),但需C++开发3,5。
- 直接继承
- 3D模型集成:
- 通过
SceneCapture2D捕捉3D场景到Render Target,转换为材质后嵌入UMG,用于角色展示或动态UI6,7。
- 通过
- 多平台适配:E
- Common UI插件扩展UMG,支持多平台输入路由和响应式布局,简化跨设备UI开发1,4。
💎 总结
UMG的底层本质是Slate框架的蓝图友好型封装,通过分层设计平衡易用性与性能:
- Slate层:处理渲染、布局、输入事件,追求极致效率;
- UMG层:提供可视化编辑、数据绑定、动画等高级功能;
- 优化核心:合批渲染、全局无效化、动态数据分离是性能关键3,5。 开发者可通过理解底层机制,在复杂UI项目中针对性优化(如减少Draw Element生成、定制Slate控件),实现高性能动态界面。
UI底层与优化

- 和目标视觉相比,自己的蓝图是不是要素过多?
- 全部展开之后,自己的蓝图是不是特别深
- 蓝图是否加载了大量的其他蓝图?
- 是否有废弃布局?
- 是否有大量CanvasPanel?
- 是否有大量的WidgetSwitcher?
对于复杂UMG(比如背包、地图的父蓝图),应以CanvasPanel为根节点,辅以Overlay为子节点。
对于简单UMG(如Tips、图标等),所有节点应以Overlay为主。(除非特殊原因)
合批
(99+ 封私信 / 18 条消息) 【UEInside】 Slate合批机制剖析 - 知乎
UMG 生命周期
https://www.cnblogs.com/sin998/p/15490311.html
- Create
- CreateWidget – 生成处理开始
- NewObject – 与UWidget相关的UObject的生成
- Initialize – 只调用一次
- OnScreen
- AddToViewport
- TakeWidget – SWidget生成开始
- RebuildWidget – SWidget生成
- Synchronize – Properties –UWidget和SWidget 同周期
- PreConstruct – Construction Script
- Construct – Begin Play
- Tick
- SlatePrepass – 包含子widget应用
- Paint – 包含子 widget 的 创建 Render Batch
- AddElement
- Remove
- RemoveFrom Viewport
- Destruct
- ReleaseSlate Resources – SWidget 的删除
- Destroy
- BeginDestroy – Widget 开始销毁
- Destructor – 析构UWidget
1 | public: |
在Game中
1 | bool Initialize()` -> `void NativeOnInitialized()` -> `void AddToScreen(ULocalPlayer* LocalPlayer, int32 ZOrder)` -> `void NativePreConstruct()` -> `void NativeConstruct()` -> `void NativeTick()` -> `void RemoveFromParent()` -> `void NativeDestruct() |
在PIE中
UMG打开:bool Initialize() -> void NativePreConstruct() 。
UMG添加控件:bool Initialize() -> void NativePreConstruct() 。
UMG拖拽控件:bool Initialize() -> void NativePreConstruct() 。
UMG删除控件:bool Initialize() -> void NativePreConstruct() 。
修改Widget内容,什么都没调用,点击编译才有调用。
UMG编译:void BeginDestroy() -> void RemoveFromParent() -> void FinishDestroy() -> bool Initialize() -> void NativePreConstruct() 。
其中,前面四个会反复调用。
UMG保存:bool Initialize() 。
获得控件和绑定事件
BindWidget这个宏是在Initialize()中完成绑定的。
绑定控件也可以手动在Initialize()或NativeOnInitialized()或NativeConstruct()中做。
那么怎么选择呢?
通过上面的分析可以知道在PIE中会调用Initialize()或NativeOnInitialized(),如果你想在PIE中就绑定(例如在PIE中预览自定义UMG就需要)并执行更新的预览的代码的话就在这里绑定。
如果你只是想在游戏中运行时才使用的话那么就在NativeConstruct()中绑定。
绑定事件在NativeOnInitialized()中做。不过要注意需要先得到控件再绑定事件,并且绑定的那个函数要加上UFUNCTION()宏。
在PIE中实时预览自定义UMG
重写Initialize():初始化并获得控件,别忘了避免空指针异常。
重写NativePreConstruct():这里写预览相关的代码,例如设置颜色、字体等。
https://zhuanlan.zhihu.com/p/636153935)

