文章目录
- 环境
- 原因
- 解决方法
- 实践
- 场景A烘焙效果,并创建A Prefab
- 场景B烘焙效果,并创建B Prefab
- 单独Load A/B Prefab + 烘焙效果
- 同时将A,B场景的内容放到同一个场景内容,同时应用不同的 lightmap 烘焙
- 方案1 - 可以同一个场景中使用多个场景的烘焙结果
- 优化案例
- 方案2 - 在单个场景中使用
- 遗留问题
- Project
- References
环境
Unity : 2020.3.37f1
Pipeline : BRP
原因
因为 unity 内置的 bake 系统是只能跟单个场景走的
并且,运行时,只有 active == true 的场景对象才有小
如果你当前 additve 的方式 load 了多个场景,并且每个场景都有自己的 lightmap
那么其他不是 active == true 的场景对象的 lightmap 将会失效
(我是没搞懂为何 unity 这功能不制作好一些,这个功能应该很多项目都会有使用到的)
恰好,我们项目之前加载关卡的代码不是使用 加载 scene 的方式
而是使用 加载 prefab 的方式,一个prefab 就是一个 scene 里面的内容
那么这个关卡中如果烘焙了 lightmap的话,走 加载 prefab 的话, lightmap 都会失效
所以才搞这么一出笔记
解决方法
只要通过运行时,设置好 Renderer.lightmapIndex
, Renderer.lightmapScaleOffset
即可
实践
场景A烘焙效果,并创建A Prefab
场景B烘焙效果,并创建B Prefab
单独Load A/B Prefab + 烘焙效果
可以看到 SingleAPrefabScene, **SingleBPrefabScene ** 场景也有 Baked Lightmaps 的内容
同时将A,B场景的内容放到同一个场景内容,同时应用不同的 lightmap 烘焙
方案1 - 可以同一个场景中使用多个场景的烘焙结果
// jave.lin : 加载自定义的 lightmap 信息using System.Collections.Generic;
using UnityEngine;[ExecuteInEditMode]
public class LoadCustomLightmapInfo : MonoBehaviour
{// jave.lin : 不要使用天空和,因为这个是在运行前决定的,// 中途设置除了 camera.clearFlag 有小,其他 renderer 的 reflection 都会有问题,// 建议使用 reflection probe 来替代//public Material skyboxMat;public List<LightmapDataAndRendererBinder> lightmapDatas;public bool refreshLightmap = false;public bool updated = true;private Dictionary<int, int> lightMapIndexDict;private void Start(){refreshLightmap = false;}private void Update(){if (!updated)return;if (!refreshLightmap){refreshLightmap = true;LightmapData[] lightmaps = null;if (lightmapDatas != null){// jave.lin : 刷新映射 idxif (lightMapIndexDict == null){lightMapIndexDict = new Dictionary<int, int>();}else{lightMapIndexDict.Clear();}// jave.lin : 统计总共使用到多少个 texture 2d array的元素// 计算 light map texture 属于哪个索引,相同的索引都会放在同一个 lightmapData 中var lightmapDataCount = 0;for (int i = 0; i < lightmapDatas.Count; i++){var lightmapDataBinder = lightmapDatas[i];if (lightmapDataBinder.lightmapData.lightmapColor == null){continue;}var key = lightmapDataBinder.lightmapData.GetTex2DHashCode();if (!lightMapIndexDict.TryGetValue(key, out int lightmapDataIDX)){lightmapDataIDX = lightmapDataCount++;lightMapIndexDict[key] = lightmapDataIDX;}lightmapDataBinder.lightmapDataIndex = lightmapDataIDX;}// jave.lin : 根据统计出来的数量作为 lightmapData 的数组大小lightmaps = new LightmapData[lightmapDataCount];for (int i = 0; i < lightmapDatas.Count; i++){var lightmapDataBinder = lightmapDatas[i];var lightmapIDX = lightmapDataBinder.lightmapDataIndex;if (lightmapIDX < -1 || lightmapIDX > lightmapDataCount - 1){continue;}var lightmapData = lightmaps[lightmapIDX];if (lightmapData == null){lightmapData = new LightmapData();lightmapData.lightmapColor = lightmapDataBinder.lightmapData.lightmapColor;lightmapData.lightmapDir = lightmapDataBinder.lightmapData.lightmapDir;lightmapData.shadowMask = lightmapDataBinder.lightmapData.shadowMask;lightmaps[lightmapIDX] = lightmapData;}// 设置 renderer 的 lightmap 属性var meshRenderer = lightmapDataBinder.meshRenderer;meshRenderer.lightmapIndex = lightmapIDX;meshRenderer.lightmapScaleOffset = lightmapDataBinder.lightmapScaleOffset;//meshRenderer.scaleInLightmap = lightmapDataBinder.scaleInLightmap;//meshRenderer.reflectionProbeUsage = UnityEngine.Rendering.ReflectionProbeUsage.BlendProbesAndSkybox;}}LightmapSettings.lightmaps = lightmaps;//RenderSettings.skybox = skyboxMat;//RenderSettings.defaultReflectionMode = UnityEngine.Rendering.DefaultReflectionMode.Skybox;}}
}
优化案例
将后续的 手动填写 LightmapDataAndRendererBinder
的方式,改用工具自动提取相关的数据即可
如果需要static batch的话,可以运行时调用 StaticBatchingUtility.Combine(parent)
来处理某个节点
方案2 - 在单个场景中使用
先在:RecordLightmapInfo2Prefab.unity 中烘焙
然后调用 RecordLightmapInfo.cs
脚本的 记录烘焙信息的功能,如下点击 RecordLightmapInfo 按钮即可
然后在另一个场景:Testing_Load_RecordLightmapInfo2Prefab.unity 中加载 RecordLightmapInfo2Prefab.prefab
并点击:CreateLightmapDatas 按钮即可
可以看到效果和在 RecordLightmapInfo2Prefab.unity 的效果是一致的
遗留问题
这种方法会导致:distance shadow mask 方式的阴影会失效
Project
- 同时加载多个场景的烘焙内容_TestingUnityLightmapLoadByCustom_unity2020.3.37f1_BRP - 2020/09/18 23:47 版本
- javelinlin/TestingUnityLightmapLoadByCustom - 打开场景:Testing_Load_RecordLightmapInfo2Prefab.unity 就可以查看效果
References
- Unity Lightmap&LightProbe局部动态加载 - 这个还有加载 light probe 的,到时如果需要的时候,我们再参考这篇文章继续完善即可
- unity动态加载Lightmap
- 【Unity】光照贴图动态加载
- Unity 动态加载LightMap