UI 性能
自动关联目录:UI 性能
1. 定位
UI 的成本主要在游戏线程:布局计算(Slate 的 Layout/Paint)与每帧重建。它不像渲染那样能在 GPU 上并行,所以 UI 卡会直接吃掉 Game 线程预算。
一句话定位:UI 优化的第一原则是"别每帧重做"——缓存、失效驱动、减少 Widget 数量。
2. 三个核心手段
| 手段 | 机制 | 适用 |
|---|---|---|
Invalidation Box | 缓存子树的绘制结果,只有失效时才重画 | 内容不常变的 UI |
Is Volatile | 反过来——标记这个 Widget 每帧都要重画 | 确实每帧变的(如倒计时) |
ListView 复用 | 条目控件复用,长列表必备 | 背包、排行榜 |
Invalidation Box + 非 Volatile 是默认应该做的:把不变的 UI 包起来,让它不再每帧重画。
注意:Invalidation Box 内的 Widget 如果标了 Is Volatile,缓存就失效了——两者是矛盾的,只对真正每帧变的东西开 Volatile。
3. 常见成本来源
| 来源 | 说明 |
|---|---|
| 属性绑定 | 每帧求值(见 UMG 深入) |
| Tick 里刷新 | 每帧重建布局 |
| Widget 数量 | 每个 Widget 都有布局与绘制成本 |
| 长列表不用复用 | ScrollBox + 大量 Widget |
| 合批失败 | 不同材质/图集打断合批 |
| 3D UI(WidgetComponent) | 每个都是一次渲染(见 3D UI) |
| 富文本 | 解析与布局成本 |
4. 合批
| 要点 | 说明 |
|---|---|
| 同材质同图集更易合批 | 把 UI 图片打成图集 |
| 减少材质切换 | 尽量共用材质 |
| 注意渲染顺序 | 层级穿插会打断合批 |
5. 参数与调试
| 命令 / 设置 | 作用 |
|---|---|
Invalidation Box | 缓存绘制 |
Is Volatile | 强制每帧重画 |
Widget.Refresh / 相关统计 | Slate 耗时 |
| Unreal Insights | 看 Slate 的 Layout/Paint 耗时 |
stat slate / Slate 统计 | UI 耗时 |
Show > Widget 相关 | 调试绘制 |
6. 代价与权衡
| 设计 | 收益 | 代价 | 什么时候不该用 |
|---|---|---|---|
Invalidation Box | 大幅省 | 缓存内存;内容变化时失效成本 | 每帧变的 UI 不该包 |
Is Volatile | 保证及时更新 | 每帧重画 | 一般不标 |
| ListView 复用 | 长列表必备 | 实现稍复杂 | 条目少时 ScrollBox 更简单 |
| 图集 | 合批 | 资产管理成本 | 简单 UI 不必 |
| 减少 Widget 数 | 直接省 | UI 表达受限 | 平衡 |
7. 踩坑与排查
| 坑 | 现象 | 怎么验证 |
|---|---|---|
| 大量属性绑定 | UI 卡 | 改委托驱动 |
| Tick 刷新文本 | 每帧重建 | 改事件驱动 |
| 长列表用 ScrollBox | 卡 | 改 ListView |
| Invalidation Box 内标 Volatile | 缓存失效 | 检查 Volatile 标记 |
| Widget 数量爆炸 | 布局慢 | 合并与复用 |
| 3D UI 太多 | 渲染成本高 | 见 3D UI 篇 |
| UI 打开时一次性构建太多 | 打开瞬间卡顿 | 分帧构建或预创建 |
8. 排查顺序
1. stat unit → Game 高才可能是 UI
2. 查属性绑定与 Tick 刷新 → 改委托/事件驱动
3. 加 Invalidation Box,检查 Volatile
4. 长列表 → ListView
5. Widget 数量与合批
6. Insights 看 Slate 的 Layout/Paint 明细参考
许可协议:CC BY
作者:Davids
本文链接:https://hustjjd.github.io/cc065871.html
更新于:2026年10月10日