3D UI 与 WidgetComponent
自动关联目录:3D UI 与 WidgetComponent
1. 定位
WidgetComponent 把 UMG 的 Widget 贴到世界中的物体上:头顶血条、交互提示、世界内的屏幕。
一句话定位:每个 WidgetComponent 都是一次独立的渲染——这是它和屏幕 UI 最本质的区别,也是成本失控的根源。
2. 用法
UPROPERTY(VisibleAnywhere)
UWidgetComponent* HpBar;
// 设置 Widget 类与空间模式
HpBar->SetWidgetClass(MyWidgetClass);
HpBar->SetWidgetSpace(EWidgetSpace::Screen); // 或 World
HpBar->SetDrawSize(FVector2D(200, 40));| 设置 | 说明 |
|---|---|
Widget Space | World(真正贴在 3D 空间)/ Screen(始终朝向相机,按 2D 绘制) |
Draw Size | Widget 的分辨率 |
Manually Redraw | 手动控制重绘(省成本) |
Redraw Time | 自动重绘间隔 |
| 材质 / 混合模式 | 如何在世界中呈现 |
3. 代价
| 成本项 | 说明 |
|---|---|
| 每个都是一次渲染 | 数量一多直接吃 draw call 与填充率 |
| World 空间还要走 3D 变换与深度 | 更贵 |
| 重绘 | 默认会定时重绘;不变的内容应手动控制 |
| 分辨率(Draw Size) | 越大越贵 |
关键优化:内容不常变的 World Widget 应设 Manually Redraw,只在数据变化时 Redraw()。这能消掉恒定重绘成本。
4. 常见用法与替代
| 需求 | 方案 |
|---|---|
| 头顶血条(数量多) | 谨慎——数量是主要成本;考虑用 Slate 批处理或自定义绘制 |
| 交互提示(近距离少量) | WidgetComponent 合适 |
| 世界内的屏幕/终端 | World 空间,少量 |
| 大量飘字 | 不该用 WidgetComponent,改用粒子或批处理 |
判断标准:同时可见的数量会不会超过十几个?会 → 不要用 WidgetComponent 做。
5. 代价与权衡
| 设计 | 收益 | 代价 | 什么时候不该用 |
|---|---|---|---|
Screen 空间 | 始终可读,像 2D | 仍是独立渲染 | — |
World 空间 | 真正融入场景 | 更贵(3D 变换、深度) | 不需要真实空间感时用 Screen |
Manually Redraw | 消掉恒定重绘 | 需要自己触发 | 内容常变的不合适 |
| 高 Draw Size | 清晰 | 成本上升 | 够用即可 |
| 大量 3D UI | — | 性能崩 | 改用批处理方案 |
6. 踩坑与排查
| 坑 | 现象 | 怎么验证 |
|---|---|---|
| 3D UI 数量过多 | 帧率掉 | 统计同时可见的 WidgetComponent 数量 |
| 一直自动重绘 | 白付成本 | 改 Manually Redraw |
| Draw Size 过大 | 贵 | 按需调小 |
| World 空间被遮挡 | 看不见 | 检查深度与材质设置 |
| 远处仍渲染 | 浪费 | 加距离剔除 |
| 文字模糊 | Draw Size 与距离不匹配 | 调整分辨率或改用 Screen 空间 |
| 与半透明排序冲突 | 排序错乱 | 见 半透明与排序 |
7. 排查顺序
1. 卡?→ 统计同时可见的 WidgetComponent 数量
2. 减少数量(距离剔除、只给近处显示)
3. 内容不变 → Manually Redraw
4. Draw Size 是否过大
5. Screen vs World 是否选对参考
许可协议:CC BY
作者:Davids
本文链接:https://hustjjd.github.io/61a300d2.html
更新于:2026年10月10日