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 SpaceWorld(真正贴在 3D 空间)/ Screen(始终朝向相机,按 2D 绘制)
Draw SizeWidget 的分辨率
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 是否选对

参考