UE5.3 Lightmass 崩溃 (GetTriangleIndices 越界) 解决笔记
UE5.3 Lightmass 崩溃 (GetTriangleIndices 越界) 解决笔记
报错症状
LightingResults: Error: <None> === Lightmass crashed: === Assertion failed: (Index >= 0) & (Index < ArrayNum) Array index out of bounds: XXX from an array of size YYY UnrealLightmass.exe!FStaticMeshStaticLightingMesh::GetTriangleIndices() UnrealLightmass.exe!FEmbreeGeometry::FEmbreeGeometry()- 烘焙静态光照时 Lightmass 进程崩溃
<None>表示崩溃日志不直接点名元凶网格- 报错是确定性的(每次同一个 index/size,崩溃点一致)
根本原因
某个 StaticMesh 的 RenderData 数据损坏:NumTriangles 与 NumIndices 不匹配,导致 Lightmass 循环处理到某处时索引数组越界。
相关源码(UE5.3):
Engine/Source/Programs/UnrealLightmass/Public/MeshExport.h- 数据结构
FStaticMeshLODData { NumTriangles, NumIndices, NumVertices } Indices[NumIndices]就是GetTriangleIndices访问的越界数组
核心解法(最快、最准)
原理:用崩溃指纹反推元凶
崩溃日志里的 size = NumIndices(索引数组大小) NumIndices / 3 = 元凶网格的三角形数(LOD0)示例:报错Array index out of bounds: 372 from an array of size 372
→372 / 3 = 124
→ 在场景里找三角形数 = 124的 StaticMesh
操作步骤
- 从崩溃日志读 size 值(例如
array of size 372) - 计算
size / 3= 元凶三角形数(例如124) - 用 UE 自带的 Asset Audit 找出该三角形数的网格:
- 顶部菜单Window → Asset Audit(或 Developer Tools → Asset Audit)
- 新建一个 Filter,按Triangle Count(三角形数)筛选
- 设置数值为
size / 3(例如 124) - 得到候选网格列表
- 找到引用该网格的 Actor:
- 在内容浏览器右键该网格 → Asset Actions → Select Actors Using This Asset
- 大纲会选中场景里所有引用它的 Actor
- 设置移动性为 Movable:
- 选中这些 Actor → Details 面板 →Mobility→ 改成Movable
- 重新 Build Lighting Only验证 → 崩溃消失即解决
为什么有效
Movable 网格不走 Lightmass,绕过了损坏的静态光照管线。在 Lumen 项目里几乎无视觉差异。
注意事项
⚠️ 改 Movable 的影响
| 类型 | 影响 |
|---|---|
| ✅ Movable/Stationary 光源 | 照常照亮,无差异 |
| ✅ Lumen GI(间接光) | 正常处理(实时间接光) |
| ✅ 实时阴影 | 正常 |
| ❌ Static Light(纯静态光) | 不再影响 Movable 网格(Lumen 项目里这种光很少) |
| ⚠️ 性能开销 | Movable 阴影实时计算。少量网格无所谓,几十上百个要评估 |
⚠️ 常见误区
| 误区 | 真相 |
|---|---|
| 用 Outliner 眼睛图标隐藏 Actor 做二分 | ❌ 隐藏的 Actor仍然进 Lightmass |
Hide In Game能排除 Build | ❌ 仍然烘焙 |
| ForceLOD=0 能救崩溃 | ❌ Lightmass 不读 ForcedLodModel |
| 编辑器显示 3 个 UV 通道 = LCI=2 合法 | ⚠️ 不一定,Lightmass 读的是 RenderData 层,可能只有 2 个 |
⚠️ 只有这几种能真正排除 Lightmass
- Mobility 改 Movable(推荐,可逆)
- 删除 Actor(Ctrl+Z 可恢复,但别中间保存)
- 移到子关卡 + Unload
- Component 取消注册
⚠️ Python API 局限(UE5.3)
- ✅
mesh.get_num_triangles(lod)可用 - ✅
mesh.get_editor_property("light_map_coordinate_index")可用 - ❌
mesh.get_num_vertices不暴露 - ❌
StaticMeshEditorSubsystem.set_lightmap_coordinate_index不暴露 - ❌
get_num_uv_channels读的是错误的层,不可信
→优先用 Asset Audit(可视化、可靠),不要依赖 Python 读底层几何数据
⚠️ 治本方向(如果元凶很多)
- StaticMesh Editor 重新导入网格 / 重建 RenderData
- 检查合并工具(Merge Actors)输出的网格是否系统性损坏
- 考虑启用
Force No Precomputed Lighting(如果项目纯 Lumen)
备用方案(当核心解法不适用时)
- 关卡级二分法:Unload 所有子关卡 → Build → 逐个 Load 定位坏关卡
- Actor 级二分法(Mobility 切换):批量改一半 Actor 为 Movable → Build → 二分缩小
- 手动重生 UV:StaticMesh Editor → Details → Build Settings → Generate Lightmap UVs → Rebuild
一句话总结
崩溃日志size N→N/3= 元凶三角形数 → Asset Audit 筛出该网格 → Find in Level → 改 Movable → Build 验证。
