Unity烘焙光打包后光照丢失问题

先说需求:我在同一个场景文件下,使用不同的场景,将场景作为预制体

但是这样有个问题:烘焙的场景没法动态加载出来

于是有这样一个脚本

csharp 复制代码
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

[DisallowMultipleComponent]
[ExecuteInEditMode]

//通过将烘焙好的光照贴图,挂到这个预制体上,运行时手动调整光照设置
public class PrefabLightmapsData : MonoBehaviour
{
    [System.Serializable]
    struct RendererInfo
    {
        public Terrain terrain;
        public Renderer renderer;
        public int lightmapIndex;
        public Vector4 lightmapOffsetScale;
    }

    [SerializeField]
    RendererInfo[] m_RendererInfo;
    [SerializeField]
    Texture2D[] m_LightmapsColor;
    [SerializeField]
    Texture2D[] _lightmaps;

    public void Init()
    {
        if (m_RendererInfo == null || m_RendererInfo.Length == 0)
            return;

        var lightmaps = LightmapSettings.lightmaps;
        var combinedLightmaps = new LightmapData[lightmaps.Length + m_LightmapsColor.Length];

        lightmaps.CopyTo(combinedLightmaps, 0);
        for (int i = 0; i < m_LightmapsColor.Length; i++)
        {
            combinedLightmaps[i + lightmaps.Length] = new LightmapData();
            combinedLightmaps[i + lightmaps.Length].lightmapColor = m_LightmapsColor[i];
            combinedLightmaps[i + lightmaps.Length].lightmapDir = _lightmaps[i];

        }

        ApplyRendererInfo(m_RendererInfo, lightmaps.Length);
        LightmapSettings.lightmaps = combinedLightmaps;
    }


    static void ApplyRendererInfo(RendererInfo[] infos, int lightmapOffsetIndex)
    {
        for (int i = 0; i < infos.Length; i++)
        {
            var info = infos[i];
            if (info.renderer != null)
            {
                info.renderer.lightmapIndex = info.lightmapIndex + lightmapOffsetIndex;
                info.renderer.lightmapScaleOffset = info.lightmapOffsetScale;
            }
            else if (info.terrain != null)
            {
                info.terrain.lightmapIndex = info.lightmapIndex + lightmapOffsetIndex;
                info.terrain.lightmapScaleOffset = info.lightmapOffsetScale;
            }
        }
    }


#if UNITY_EDITOR
    [UnityEditor.MenuItem("Tools/Bake Prefab Lightmaps")]
    static void GenerateLightmapInfo()
    {
        if (UnityEditor.Lightmapping.giWorkflowMode != UnityEditor.Lightmapping.GIWorkflowMode.OnDemand)
        {
            Debug.LogError("ExtractLightmapData requires that you have baked you lightmaps and Auto mode is disabled.");
            return;
        }
        UnityEditor.Lightmapping.Bake();

        PrefabLightmapsData[] prefabs = GameObject.FindObjectsOfType<PrefabLightmapsData>();

        foreach (var instance in prefabs)
        {
            var gameObject = instance.gameObject;
            var rendererInfos = new List<RendererInfo>();
            var lightmapsColor = new List<Texture2D>();
            List<Texture2D> lightmapsDir = new List<Texture2D>();

            GenerateLightmapInfo(gameObject, rendererInfos, lightmapsColor, lightmapsDir);

            instance.m_RendererInfo = rendererInfos.ToArray();
            instance.m_LightmapsColor = lightmapsColor.ToArray();
            instance._lightmaps = lightmapsDir.ToArray();


            var targetPrefab = PrefabUtility.GetCorrespondingObjectFromOriginalSource(instance.gameObject) as GameObject;
            if (targetPrefab != null)
            {
                GameObject root = PrefabUtility.GetOutermostPrefabInstanceRoot(instance.gameObject);

                if (root != null)
                {
                    GameObject rootPrefab = PrefabUtility.GetCorrespondingObjectFromSource(instance.gameObject);
                    string rootPath = AssetDatabase.GetAssetPath(rootPrefab);
                    PrefabUtility.UnpackPrefabInstanceAndReturnNewOutermostRoots(root, PrefabUnpackMode.OutermostRoot);
                    try
                    {
                        PrefabUtility.ApplyPrefabInstance(instance.gameObject, InteractionMode.AutomatedAction);
                    }
                    catch { }
                    finally
                    {
                        PrefabUtility.SaveAsPrefabAssetAndConnect(root, rootPath, InteractionMode.AutomatedAction);
                    }
                }
                else
                {
                    PrefabUtility.ApplyPrefabInstance(instance.gameObject, InteractionMode.AutomatedAction);
                }
            }
        }
    }

    static void GenerateLightmapInfo(GameObject root, List<RendererInfo> rendererInfos, List<Texture2D> lightmapsColor, List<Texture2D> lightmapsDir)
    {
        var renderers = root.GetComponentsInChildren<MeshRenderer>();
        foreach (MeshRenderer renderer in renderers)
        {
            if (renderer.lightmapIndex != -1)
            {
                RendererInfo info = new RendererInfo();
                info.renderer = renderer;
                if (renderer.lightmapScaleOffset != Vector4.zero)
                {
                    info.lightmapOffsetScale = renderer.lightmapScaleOffset;
                    Texture2D lightmapColor = LightmapSettings.lightmaps[renderer.lightmapIndex].lightmapColor;
                    Texture2D lightmapDir = LightmapSettings.lightmaps[renderer.lightmapIndex].lightmapDir;

                    info.lightmapIndex = lightmapsColor.IndexOf(lightmapColor);
                    if (info.lightmapIndex == -1)
                    {
                        info.lightmapIndex = lightmapsColor.Count;
                        lightmapsColor.Add(lightmapColor);
                        lightmapsDir.Add(lightmapDir);
                    }

                    rendererInfos.Add(info);
                }
            }
        }

        var Terrainrenderers = root.GetComponentsInChildren<Terrain>();
        foreach (var terrain in Terrainrenderers)
        {
            if (terrain.lightmapIndex != -1)
            {
                RendererInfo info = new RendererInfo();
                info.terrain = terrain;
                if (terrain.lightmapScaleOffset != Vector4.zero)
                {
                    info.lightmapOffsetScale = terrain.lightmapScaleOffset;
                    Texture2D lightmapColor = LightmapSettings.lightmaps[terrain.lightmapIndex].lightmapColor;
                    Texture2D lightmapDir = LightmapSettings.lightmaps[terrain.lightmapIndex].lightmapDir;

                    info.lightmapIndex = lightmapsColor.IndexOf(lightmapColor);
                    if (info.lightmapIndex == -1)
                    {
                        info.lightmapIndex = lightmapsColor.Count;
                        lightmapsColor.Add(lightmapColor);
                        lightmapsDir.Add(lightmapDir);
                    }

                    rendererInfos.Add(info);
                }
            }
        }
    }
#endif
}

把这个脚本挂在场景预制体上,烘焙完成后生成贴图,之后运行时调用Init方法就可以了

这个脚本代码是没问题的,但是实际上打包后,却发现整个场景经常性没有光照!也就是场景纯黑的,只有偶尔情况下才会有光照

经过多次测试,我发现是Lighting Data Asset为None导致的,如图1

【图1】

即使给预制体挂好了脚本和烘焙信息,也是会出现问题,只有给Lighting Data Asset拖拽上光照数据,才是正常的,如图2

【图2】

这样再打包就正常了

相关推荐
空中海15 小时前
第二篇:Unity中级阶段(核心开发能力)
unity·游戏引擎
DaLiangChen1 天前
Unity 实用工具:动态绘制物体边界包围盒(支持屏幕固定线宽)
unity·游戏引擎
张老师带你学1 天前
Unity 食物 农产品相关
科技·游戏·unity·游戏引擎·模型
mxwin1 天前
Unity Custom Interpolators与半透明阴影的原理与实战
unity·游戏引擎·shader
晴夏。1 天前
UE5第三人称模板实现及相关引擎源码分析
unity·ue5·游戏引擎·ue
天人合一peng1 天前
Unity工程发布hololens需安装, MRTK安装
unity·游戏引擎·hololens
魔士于安1 天前
Unity类似博物馆场景
前端·unity·游戏引擎·贴图·模型
小拉达不是臭老鼠1 天前
Unity数据持久化_XML
学习·unity
RReality1 天前
【Unity Shader URP】模板遮罩 / 传送门 实战教程
ui·unity·游戏引擎·图形渲染·材质
zdr尽职尽责2 天前
Untiy 处理Aseprite 资产 解决偏移问题
学习·unity·c#·游戏引擎