Slate 实践

自动关联目录:Slate 实践

1. 定位

Slate 是 UE 底层的 C++ UI 框架,编辑器自身就是用它写的。UMG 建立在它之上。

一句话定位:绝大多数游戏 UI 用 UMG 就够;只有两类场景需要直接写 Slate——编辑器扩展,以及需要极致性能/自定义绘制的控件。

2. 结构

SWidget(Slate 层)
   ├── SCompoundWidget  有一个子控件
   ├── SPanel           有多个子控件(布局容器)
   ├── SLeafWidget      无子控件
   └── STextBlock / SImage / SButton ...
概念说明
SWidget基类
声明式语法SNew(STextBlock).Text(...)
ConstructSlate 侧的构造(在 FArguments 里)
Tick每帧(需显式启用)
OnPaint自定义绘制
ComputeDesiredSize自定义布局尺寸
SNew(SVerticalBox)
+ SVerticalBox::Slot().AutoHeight()
  [ SNew(STextBlock).Text(FText::FromString(TEXT("Hi"))) ]
+ SVerticalBox::Slot().FillHeight(1.f)
  [ SNew(SButton).OnClicked(this, &SMyWidget::OnClick) ]

3. 什么时候用 Slate

场景用
常规游戏 UIUMG
编辑器扩展Slate(见 Editor Extension)
高性能长列表Slate + 虚拟化,或 UMG 的 ListView
自定义绘制Slate(OnPaint)
需要与 UObject/GC 集成UMG

4. 与 UMG 的关系

SlateUMG
层底层 C++UObject 封装
编辑代码可视化
GC不参与参与
性能更高多一层
上手难容易

UMG 的 UWidget 内部就持有 SWidget——两者不是竞争关系,而是包装关系。想在 UMG 里嵌入自定义 Slate,可以重写 RebuildWidget()。

5. 代价与权衡

设计收益代价什么时候不该用
Slate性能最高、可控代码量大、无可视化、无 GC常规 UI 不该用
UMG可视化、蓝图、GC多一层性能极致时可考虑 Slate
自定义 OnPaint任意绘制要自己处理布局与失效能用内置控件就不要
Slate Tick每帧更新每帧成本尽量事件驱动

6. 踩坑与排查

坑现象怎么验证
用 Slate 写常规 UI开发效率低改用 UMG
Slate 里持有 UObject 裸指针崩溃(见 GC)用 TWeakObjectPtr
自定义 OnPaint 忘记失效不刷新正确触发 Invalidate
Slate Tick 全开每帧成本只给必要的开
布局没实现 ComputeDesiredSize尺寸为 0实现它
在 Slate 里做游戏逻辑与 UMG 同理见 Security

7. 排查顺序

1. 先确认是不是真的需要 Slate(常规 UI 用 UMG)
2. 布局问题 → 检查 Slot 与 ComputeDesiredSize
3. 不刷新 → Invalidate
4. 崩溃 → 是否持有 UObject 裸指针
5. 性能 → 减少 Tick,检查 OnPaint 复杂度

参考