UMG生成路径
前言
探索从UMG到Slate后加载的全过程
简述
UMG流程:
CreateWidget
↓
生成 UWidget / WidgetTree
↓
AddToViewport / AddChild
↓
TakeWidget
↓
RebuildWidget
↓
生成真实 SWidget
↓
触发首次创建后的逻辑,也就是 NewlyCreated 相关流程
GPT回答
从源码角度看,UE 里 UMG 从“蓝图/类”生成到屏幕上的过程,大致是这条链路:
UWidgetBlueprint → 编译生成 UWidgetBlueprintGeneratedClass → 运行时 CreateWidget 创建 UUserWidget → Initialize / RebuildWidget 构建 Slate 树 → AddToViewport 加入 viewport → Slate 每帧布局、绘制、输入分发。
1. 编辑器里创建 UMG 蓝图
UMG 蓝图资源类型通常是 UWidgetBlueprint。
源码里相关模块大概在:
1 | Engine/Source/Editor/UMGEditor |
一个 Widget Blueprint 里主要包含:
1 | UWidgetTree* WidgetTree; |
WidgetTree 保存你在设计器里拖出来的控件层级,比如:
1 | CanvasPanel |
这些不是 Slate 控件,而是 UObject 体系里的 UMG 控件对象,例如:
1 | UCanvasPanel |
它们都继承自 UWidget。
2. 编译 Widget Blueprint
UMG 蓝图编译后会生成:
1 | UWidgetBlueprintGeneratedClass |
它继承自:
1 | UBlueprintGeneratedClass |
比较关键的是它会保存编译后的 WidgetTree 模板、绑定信息、动画信息等。
运行时创建 Widget 时,不是直接使用编辑器里的 UWidgetBlueprint,而是使用它编译出来的 generated class。
概念上类似:
1 | UWidgetBlueprint |
3. 运行时 CreateWidget
常见代码是:
1 | UUserWidget* Widget = CreateWidget<UUserWidget>(PlayerController, WidgetClass); |
源码入口通常会走到 UMG 的创建逻辑,核心目标是创建一个 UUserWidget 实例。
流程可以理解为:
1 | CreateWidget |
Initialize() 是很关键的一步。
它会根据 UWidgetBlueprintGeneratedClass 中保存的模板数据,初始化当前实例的 WidgetTree,并处理:
1 | 控件实例化 |
如果蓝图里某个控件勾选了 Is Variable,生成类中会让对应的 C++/蓝图成员变量指向运行时创建出来的那个控件实例。
例如蓝图里有一个按钮 StartButton,运行时就会绑定到:
1 | UButton* StartButton; |
4. UWidgetTree 生成 UObject 控件树
此时得到的是 UMG 层的控件树,也就是 UObject 控件树。
例如:
1 | UUserWidget |
这些对象本身还不是最终渲染用的 Slate widget。
UMG 的核心思想是:
1 | UMG = UObject 封装层 |
也就是说,UButton、UTextBlock 等 UMG 控件最终会构建出对应的 Slate 控件:
1 | UButton -> SButton |
5. RebuildWidget 构建 Slate 树
当 Widget 需要真正显示时,会调用:
1 | UUserWidget::RebuildWidget() |
以及各个子控件自己的:
1 | UWidget::RebuildWidget() |
比如:
1 | UButton::RebuildWidget() |
UTextBlock 会创建 STextBlock,UImage 会创建 SImage。
所以 UMG 树会被转换成 Slate 树:
1 | UCanvasPanel -> SConstraintCanvas |
最终类似:
1 | SObjectWidget |
SObjectWidget 是 UMG 和 Slate 之间的重要桥接层,它把 UUserWidget 包成 Slate 可以管理的 SWidget。
6. AddToViewport
当你调用:
1 | Widget->AddToViewport(); |
通常会进入:
1 | UUserWidget::AddToViewport() |
最后通过 UGameViewportClient 把它加到 viewport 的 widget 层中。
概念上是:
1 | UUserWidget::AddToViewport() |
Slate 层最终会把这个 Widget 加到游戏 viewport 对应的 Slate 容器中。
7. Slate 负责布局、绘制和输入
一旦进入 Slate 树,后续每帧主要由 Slate 系统处理:
1 | Prepass |
也就是:
1 | 计算 DesiredSize |
UMG 的属性变更,例如修改 TextBlock 的文字:
1 | TextBlock->SetText(FText::FromString("Hello")); |
最终会同步到对应的 Slate 控件:
1 | STextBlock::SetText(...) |
整体流程图
1 | 编辑器设计 UMG |
一句话总结:
UMG 蓝图本质上先被编译成 UWidgetBlueprintGeneratedClass,运行时 CreateWidget 创建 UUserWidget 和它的 UWidgetTree,然后每个 UWidget 通过 RebuildWidget() 生成对应的 Slate SWidget,最后 AddToViewport() 把 Slate 树挂到游戏 viewport 上,由 Slate 系统完成布局、绘制和输入。
分析图


