如何程序化放置Light Probe减少人工摆放

解读

在国内 Unity 项目面试中,这道题表面问“怎么少点鼠标”,实质考察三点:

  1. 你对 Light Probe 光照一致性 的理解深度——放少了漏光、放多了烘焙爆炸;
  2. 能否用 C# + Unity Editor 扩展 把“经验”转成“算法”,让策划/美术一键生成;
  3. 运行时内存、烘焙时间、场景复杂度 的权衡意识,体现“资深”而非“外包”。

知识点

  • Light Probe 本质:稀疏采样空间光照,供动态物体插值,密度决定 SH 数据量
  • 放置原则“关键阴影过渡区 + 动态物体活动区”,避免均匀铺满;
  • 程序化手段: – NavMesh/Heightmap 射线 找“可行走面”,剔除墙内/空中点; – Voxel/八叉树 划分空间,光照梯度变化大的区域自适应细分; – 聚类合并:对相似 SH 系数(L2 距离 < ε)的 Probe 做 K-Means 合并,减少 30-50% 数量; – 烘焙前验证:用 LightProbeGizmo 可视化漏光区域,再局部加密;
  • 工程落地: – 写成 EditorWindow + ScriptableWizard,支持“一键生成/回退/保存Asset”; – 提供 密度滑杆、LOD 级联、黑白密度图 Mask,让美术有“控制感”; – 把生成的 Probe 位置序列化到 ScriptableObject,避免场景文件冲突,方便版本管理;
  • 性能红线:移动端场景建议 ≤1 万个 Probe,SH 系数存储 L2 阶即可,否则包体与加载时间双双爆炸。

答案

“我在上一个开放世界手游项目里,用三步把 3 万个人工 Probe 降到 6 千个,且动态物体光照误差 < 3%。 第一步,用 NavMesh 采样可行走点作为种子,射线检测上方 0.5-3 m 空间,剔除室内天花板内部点; 第二步,构建 1 m³ 的初始体素,计算每个体素内光照梯度(直接取相邻体素 SH 系数的 L2 距离),梯度 > 阈值则八叉树细分到 0.25 m³,直到梯度 < 阈值或达到最小体素; 第三步,对最终体素中心做 K-Means 聚类,合并相似 SH 的 Probe,再人工标记‘剧情战斗区’ Mask 强制保留高密度; 最后把算法封装成 LightProbeGeneratorEditor,提供密度滑杆、黑白 Mask 贴图、Undo 记录,策划 5 秒完成重新布点。烘焙时间从 45 min 降到 12 min,包体光照数据减少 38%,iPhone 8 上动态角色渲染耗时无变化。”

拓展思考

  1. 运行时动态 Probe:如果场景昼夜交替,可预烘焙两套 SH 数据,用 Unity 2022+ Probe Volume 做 Streaming,按 Chunk 加载,节省 60% 内存;
  2. GPU Driven 放置:Compute Shader 并行计算光照梯度,百万个体素 0.2 s 完成,适合大地形;
  3. 与 SRP 结合:URP 的 Probe Volume 已支持虚拟化,未来项目可直接放弃传统 Probe,改用 APV(Adaptive Probe Volume),但 Shader 自定义采样需兼容;
  4. 面试加分项:提到“把算法写成 Jenkins nightly 检查,当美术合并场景后 Probe 数量异常自动打回”,体现持续集成思维,国内大厂非常吃这一套。