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

操作步骤

  1. 从崩溃日志读 size 值(例如array of size 372
  2. 计算size / 3= 元凶三角形数(例如124
  3. 用 UE 自带的 Asset Audit 找出该三角形数的网格
    • 顶部菜单Window → Asset Audit(或 Developer Tools → Asset Audit)
    • 新建一个 Filter,按Triangle Count(三角形数)筛选
    • 设置数值为size / 3(例如 124)
    • 得到候选网格列表
  4. 找到引用该网格的 Actor
    • 在内容浏览器右键该网格 → Asset Actions → Select Actors Using This Asset
    • 大纲会选中场景里所有引用它的 Actor
  5. 设置移动性为 Movable
    • 选中这些 Actor → Details 面板 →Mobility→ 改成Movable
  6. 重新 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)

备用方案(当核心解法不适用时)

  1. 关卡级二分法:Unload 所有子关卡 → Build → 逐个 Load 定位坏关卡
  2. Actor 级二分法(Mobility 切换):批量改一半 Actor 为 Movable → Build → 二分缩小
  3. 手动重生 UV:StaticMesh Editor → Details → Build Settings → Generate Lightmap UVs → Rebuild

一句话总结

崩溃日志size NN/3= 元凶三角形数 → Asset Audit 筛出该网格 → Find in Level → 改 Movable → Build 验证。