1. 项目概述:为什么URP烘焙场景是个技术活?
如果你是从Unity内置渲染管线(Built-in Render Pipeline)时代过来的老手,或者刚接触Unity不久,正被各种渲染管线搞得晕头转向,那么“在URP里烘焙场景”这件事,很可能让你踩过不少坑。我见过太多项目,从内置管线切换到URP后,光照烘焙(Light Baking)要么效果诡异,要么直接失败,烘焙出来的场景要么一片死黑,要么漏光严重,和内置管线下的效果天差地别。
这背后的核心原因在于,通用渲染管线(URP)并非内置管线的简单升级或“高清版”,而是一套从底层架构到光照系统都重新设计的渲染方案。内置管线那套用了多年的“自动”烘焙逻辑,在URP里并不完全适用。URP为了追求跨平台的高性能和更简洁的渲染路径,对光照贴图(Lightmap)、光照探头(Light Probe)和反射探头(Reflection Probe)的生成与使用方式做了诸多调整。如果你还沿用老一套的“摆好灯光 -> 标记Static -> 点击Generate Lighting”的流程,大概率会得到令人失望的结果。
这篇教程的目的,就是帮你彻底理清在URP下进行高质量场景光照烘焙的完整流程、核心原理以及那些官方文档里不会明说的“潜规则”。我们将从URP光照系统的设计思路讲起,一步步拆解从场景准备、参数配置到最终烘焙优化的全流程,并分享我实际项目中积累的避坑经验。无论你是为了提升移动端性能而烘焙静态光照,还是希望在PC上获得更真实的间接光照效果,这篇文章都能给你一套清晰、可落地的解决方案。
2. URP光照系统核心解析:与内置管线的本质区别
在动手烘焙之前,我们必须先理解URP处理光照的底层逻辑,这是避免后续所有问题的关键。
2.1 光照模式的演变:从“模式”到“混合模式”的消亡
在内置管线中,灯光的Mode(模式)属性(Realtime, Baked, Mixed)是控制光照行为的核心。一个设置为Baked的灯光,其所有光照信息(直接光、阴影、间接光)都会被烘焙到光照贴图中。而在URP中,这个经典的三元划分被大幅简化了。
URP引入了一个更全局化的概念:Lighting Mode(光照模式),它在Window > Rendering > Lighting设置面板中。这里主要有两个选项:Baked Indirect(烘焙间接光)和Shadowmask(阴影遮罩)。那个经典的“Subtractive”模式在URP中已不被推荐使用。
这个变化意味着什么?意味着单个灯光不再独立决定自己是“实时”还是“烘焙”。相反,整个场景的光照策略由这个全局的Lighting Mode决定,再结合每个GameObject的Contribute Global Illumination(贡献全局光照)和Receive Global Illumination(接收全局光照)复选框,以及灯光本身的属性来共同作用。
注意:这是新手最容易困惑的点。在URP里,你不能再只盯着一个灯光的Mode属性,而必须从“场景-物体-灯光”三个层面协同配置。
2.2 核心组件:光照贴图、光照探头与反射探头
尽管管线变了,但光照烘焙的三大核心输出没变:
- 光照贴图(Lightmaps):存储静态物体表面接收到的烘焙光照(颜色、阴影)的纹理图集。URP默认使用渐进光照贴图器(Progressive Lightmapper),支持CPU和GPU加速,比内置管线时代的Enlighten更快、更直观。
- 光照探头(Light Probes):用于给场景中的动态物体(如角色、可移动道具)提供间接光照。这是保证动态物体能与烘焙环境完美融合、不显得“飘”或“黑”的关键。URP对光照探头的依赖性与内置管线一致。
- 反射探头(Reflection Probes):捕获场景特定位置的周围环境,生成立方体贴图(Cubemap),用于物体表面的反射效果。对于金属、水面等材质至关重要。
URP与内置管线的主要区别在于这些数据的生成算法、存储格式以及与Shader的交互方式。URP的Shader使用不同的方式去采样光照贴图和探头数据,因此内置管线的材质球直接拿到URP项目里,很可能会因为无法正确读取这些数据而显示错误。
2.3 静态与动态的划分:Contribute GI 与 Receive GI
这是烘焙前的准备工作,也是最容易出错的一步。在Hierarchy中选中一个静态物体(如墙壁、地板),在Inspector窗口的右上角,你会看到Static复选框。点击旁边的小箭头,会展开更详细的静态选项。
对于光照烘焙,最关键的是这两项:
- Contribute Global Illumination:勾选后,该物体会向场景发射间接光照。例如,一个被阳光照亮的白色墙壁,它会将光线反射到周围,这个“反射光”的计算就依赖于这个选项。只有勾选了此项的物体,才会在烘焙时被考虑为间接光的“发射源”。
- Receive Global Illumination:勾选后,该物体会接收来自其他物体的烘焙间接光照以及直接光的烘焙阴影。通常我们希望静态物体都接收GI。
一个常见的误区是:把所有不动的物体都标记为Static。对于大型、复杂或数量众多的物体(如一片由无数小石块组成的碎石堆),如果全部标记为“Contribute GI”,会急剧增加光照贴图的计算量和内存占用。正确的做法是:只有那些表面平滑、面积较大、对间接光贡献明显的物体(如主要墙面、地面、天花板)才勾选“Contribute GI”。对于碎石、草丛、小装饰品等,通常只勾选“Receive GI”,它们的间接光照依赖光照探头来近似获取。
3. URP场景烘焙全流程实操指南
理解了原理,我们开始实战。以下是一个从零开始的URP场景标准烘焙流程。
3.1 第一步:项目与场景基础配置
- 创建或转换URP项目:如果你是新项目,在Unity Hub创建时直接选择“Universal RP”模板。如果是旧项目迁移,需要通过Package Manager安装“Universal RP”包,然后创建或指定一个URP Asset(通常是一个
.asset文件),并在Project Settings -> Graphics中将其设为当前渲染管线。 - 配置URP Asset:双击你的URP Asset文件,进行关键设置。
- 主光源:确保场景中有一个方向光(Directional Light),这是你的太阳/主光源。在URP中,通常建议将其Mode设置为Mixed。在Lighting窗口的Mixed Lighting部分,选择Baked Indirect或Shadowmask模式后,这个Mixed光源的直射光会是实时的,而阴影和间接光会被烘焙。
- 环境光:在Lighting窗口的Environment标签页下,设置Source为Color或Gradient,并赋予一个基础颜色。这是场景没有直接光照区域的基础亮度,对烘焙氛围影响很大。
- 雾效:如果需要,在URP Asset中启用并配置Fog。烘焙不会影响雾效,但它是整体氛围的一部分。
3.2 第二步:灯光与物体设置
- 布置灯光:根据你的场景需求布置灯光。记住URP的灯光策略:
- 方向光(太阳):通常用Mixed模式。
- 点光源/聚光灯(室内灯具):如果灯具本身是静态的(不会移动、变色),可以将其设为Baked模式,这样它的所有光照信息都会被烘焙,运行时零消耗。如果是可开关或变色的灯,则需设为Realtime或Mixed。
- 区域光(Area Light):在URP中,区域光只能被烘焙,无法实时。这是模拟窗户入射光、灯带等面光源效果的神器。
- 标记静态物体:选中所有构成场景主体的静态模型(建筑、地形、大型家具)。
- 勾选右上角的Static复选框(这会自动勾选所有子选项)。
- 手动检查:对于复杂场景,建议取消勾选“Static”,然后仅勾选“Contribute GI”和“Receive GI”。避免不必要的“Occluder Static”等选项增加遮挡计算负担。
- 对于大量重复的小物体(如一堆书、散落的树叶):将它们放入一个父物体下,父物体不标记Static,而使用**光照探头代理体(Light Probe Proxy Volume, LPPV)**来为这个群体提供更精确的间接光照,这比给每个小物体单独烘焙或依赖单个探头效果好得多。
3.3 第三步:Lighting窗口深度配置
打开Window > Rendering > Lighting,这是烘焙的控制中心。
- Scene标签页:
- Lighting Mode:选择Baked Indirect或Shadowmask。对于移动端或性能优先的项目,Baked Indirect是首选,它只烘焙间接光,实时阴影质量高。Shadowmask能提供更高质量的静态阴影与动态物体的阴影混合,但需要更多纹理内存。
- Lightmapping Settings:
- Lightmapper:选择Progressive GPU(如果你有不错的显卡)或Progressive CPU。GPU通常快很多。
- Direct Samples/Indirect Samples/Environment Samples:采样数。新手可以先从64开始,预览效果,最终烘焙时根据质量要求提升到256、512甚至更高。采样数直接影响噪点多少和烘焙时间。
- Lightmap Resolution:单位:texels per unit(每单位纹理像素)。这是最重要的质量参数之一。室内小场景可以从30-50开始,大型室外场景可能只需要5-10。分辨率越高,光照细节越清晰,但光照贴图尺寸会呈平方级增长。
- Lightmap Padding:光照贴图图集中各图表之间的间隔,防止 bleeding(漏光)。通常保持默认(2)即可,如果发现漏光严重,可以增加到4或8。
- Max Lightmap Size:单张光照贴图的最大尺寸。移动端建议从1024开始,PC端可用2048或4096。URP会尝试将所有静态物体的光照信息打包进这个尺寸的图集中。
- Compress Lightmaps:压缩光照贴图。务必勾选,能大幅减少内存占用,对画质影响在可接受范围内。
- Environment标签页:配置天空盒、环境光等,前文已提及。
- Light Probes标签页:可以创建和编辑光照探头组。对于动态物体行走的区域,需要手动或自动放置足够密集的光照探头。
3.4 第四步:烘焙执行与监控
- 生成光照探头:在场景中动态物体活动的区域,使用GameObject > Light > Light Probe Group创建一组探头,并手动拖动这些黄色小球到关键位置,如房间角落、门口、楼梯上下。一个简单的原则是:在光照可能发生突变的地方(如明暗交界处)放置更密集的探头。
- 生成反射探头:在需要高质量反射的大厅、水池等区域,通过GameObject > Light > Reflection Probe放置。调整其Box Size覆盖所需区域,选择Baked模式,然后点击Bake按钮单独烘焙它。
- 开始烘焙:回到Lighting窗口的Scene标签页,点击底部的Generate Lighting按钮。如果使用Progressive Lightmapper,你会看到一个实时更新的预览窗口,可以观察光照收敛的过程。在预览效果满意后,再点击“Pause”并选择“Bake”来完成最终烘焙。
4. 常见问题、性能优化与避坑实录
即使按照流程操作,你可能还是会遇到各种问题。下面是我总结的“血泪”经验。
4.1 烘焙结果异常问题排查
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 场景一片漆黑 | 1. 主光源模式错误(如设为Baked但没执行烘焙)。 2. 环境光(Environment Lighting)强度为0。 3. 相机的渲染层级被意外修改。 | 1. 检查方向光模式是否为Mixed或Realtime,并确认已执行烘焙。 2. 在Lighting窗口的Environment标签页,调高Environment Lighting的Intensity Multiplier。 3. 检查相机Culling Mask是否包含了所有层。 |
| 严重的漏光(Light Bleeding) | 1. 光照贴图分辨率过低。 2. Lightmap Padding值太小。 3. 模型UV重叠或UV2展开不当。 | 1. 提高Lightmap Resolution。 2. 增加Lightmap Padding值(如从2调到4)。 3.这是最常见原因!确保所有参与烘焙的静态模型拥有独立、不重叠的第二套UV(UV2),用于光照贴图。可以在模型导入设置中勾选“Generate Lightmap UVs”,或使用3D软件精心展开。 |
| 动态物体“飘”在空中,与环境光不融合 | 动态物体缺少光照探头照明,或探头放置不当。 | 1. 确保动态物体所在区域有Light Probe Group覆盖。 2. 检查动态物体上的MeshRenderer组件,确保“Use Light Probes”选项被勾选。 3. 增加探头密度,尤其是在光影变化区域。 |
| 烘焙时间极长 | 1. 采样数(Samples)设置过高。 2. 标记为“Contribute GI”的物体太多或太复杂。 3. 光照贴图分辨率过高或尺寸过大。 4. 使用了CPU Lightmapper。 | 1. 先使用低采样(如64)预览,最终烘焙时再提高。 2. 按2.3节原则,减少不必要的“Contribute GI”物体。 3. 降低Lightmap Resolution和Max Lightmap Size。 4. 切换到Progressive GPU(需支持CUDA或OptiX的N卡)。 |
| 烘焙后阴影边缘有锯齿或闪烁 | 1. 阴影过滤(Shadow Filtering)设置问题。 2. 对于Mixed光源,阴影过渡距离(Shadow Distance)设置不当。 | 1. 在URP Asset的Shadow配置中,尝试不同的Filtering模式(如PCF)。 2. 调整Quality设置中的Shadow Distance,确保在摄像机近处使用实时阴影,远处平滑过渡到烘焙阴影。 |
4.2 性能优化黄金法则
- 分辨率与尺寸的平衡:不要盲目追求高分辨率。一个
4096x4096的光照贴图占用内存是1024x1024的16倍!通过Lightmap Resolution和Max Lightmap Size共同控制总内存消耗。使用Lightmap Stats(Lighting窗口底部)查看当前场景的光照贴图总大小和图表数量,目标是图表数量尽可能少(减少Draw Call),单张图集利用率高(减少浪费)。 - 善用光照探头代理体(LPPV):对于由大量相同小物体组成的集群(如森林、人群),为父物体添加一个Light Probe Proxy Volume组件,并调整其边界。这允许动态物体从该体积内的一个3D网格中插值获取光照,比使用单个或少数几个光照探头精确得多,且性能远优于为每个小物体单独烘焙。
- 分层烘焙:对于超大型开放世界,一次性烘焙整个场景是不现实的。可以将世界划分为多个区块(如地形区块、建筑内部),分别烘焙,并通过精心放置的光照探头在区块边界进行光照衔接。Unity的Lighting Data Asset可以让你保存和加载不同场景的光照数据。
- 烘焙与实时的混合策略:URP的Shadowmask模式是性能与质量的优秀折衷。它允许静态物体与静态物体之间的阴影使用高质量的烘焙阴影,而动态物体投射到静态物体上、或静态物体投射到动态物体上的阴影,则使用实时阴影。这既保证了静态场景的阴影质量,又保持了动态交互的灵活性。在Lighting窗口的Shadowmask模式下,可以设置Distance Shadowmask,在摄像机一定距离内使用实时阴影与烘焙阴影的混合,超出距离后则完全使用烘焙阴影,进一步优化性能。
4.3 材质与Shader的适配
这是从内置管线迁移到URP时最大的痛点之一。内置管线的标准材质(Standard Shader)不兼容URP。如果你的模型材质显示粉色(Missing Shader),你需要将它们转换为URP支持的材质。
- 批量转换:Unity提供了迁移工具。在编辑器中,选择Edit > Render Pipeline > Universal Render Pipeline,然后选择Upgrade Project Materials to UniversalRP Materials。务必在操作前备份项目!此操作会尝试将项目中的所有标准材质转换为URP Lit着色器。
- 手动检查:自动转换并非100%完美,特别是使用了复杂自定义节点的材质。转换后,需要逐个检查重要材质,确保法线贴图、金属度、光滑度、自发光等通道映射正确。URP Lit着色器的参数布局与Standard Shader有所不同,需要熟悉一下。
- 自定义Shader:如果你或你的资源包使用了自定义Shader,必须使用Shader Graph重写,或者修改HLSL代码以兼容URP的库函数和光照模型。这是迁移过程中技术成本最高的部分。
5. 进阶技巧:提升烘焙质量与效率
当你掌握了基础流程后,下面这些技巧能让你的场景光照更上一层楼。
- 利用光照贴图通道(Lightmap Index & Scale/Offset):在代码中,你可以通过
MeshRenderer.lightmapIndex和MeshRenderer.lightmapScaleOffset来动态控制物体使用哪一张光照贴图以及如何采样。这可以用于实现动态加载不同区域的光照数据,或者对同一物体使用多套光照贴图以实现昼夜循环切换。 - 烘焙光照探头(Baked Light Probes):除了自动生成,你还可以手动烘焙光照探头组的数据,使其包含精确的间接光信息。在Light Probe Group的Inspector中,点击“Bake”按钮(需在Lighting窗口中启用Baked GI)。这对于固定场景中动态物体的光照准确性至关重要。
- 调试视图:在Scene视图的右上角,打开Shading Mode下拉菜单,选择Global Illumination下的Baked Lightmap、Directionality或Shadowmask等视图。这些调试视图能让你直观地看到烘焙结果的数据分布、方向性和阴影遮罩,是排查问题的利器。
- 脚本控制烘焙:对于需要频繁迭代的团队,可以通过脚本API(如
Lightmapping.BakeAsync())将烘焙流程自动化,集成到CI/CD流水线中。你可以编写编辑器脚本,在代码中设置所有Lighting参数,然后触发烘焙,并保存Lighting Data Asset。
光照烘焙从来都不是一个“一键搞定”的魔法按钮,尤其是在URP这套更现代、也更需要手动微调的体系下。它要求开发者对光照原理、性能权衡和工具链有更深的理解。我的经验是,耐心比技术更重要。花时间调整一个参数,观察其影响;为一个复杂的角落精心布置一组光照探头;反复试验不同的Lighting Mode组合。这个过程本身,就是对场景艺术表现力和技术实现深度的一次绝佳修炼。当你看到动态角色完美地融入精心烘焙的光影环境中,那种虚实结合的沉浸感,便是对所有努力的最佳回报。