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】

这样再打包就正常了

相关推荐
GLDbalala9 小时前
Unity 实现一个简单的构建机
unity·游戏引擎
JIes__1 天前
Unity(二)——Resources资源动态加载
unity·游戏引擎
地狱为王1 天前
Unity使用NovaSR将沉闷的16kHz音频升频成清晰的48kHz音频
unity·游戏引擎·音视频·novasr
dzj20211 天前
Unity中使用LLMUnity遇到的问题(二)——LLMUnity脚本学习和探索
unity·llmunity
警醒与鞭策1 天前
Cursor Agent Skill 原理及LLM , Agent, MCP ,Skill区别
android·unity·ai·cursor
tealcwu2 天前
【Unity资源】Unity MCP 介绍
unity·游戏引擎
Thomas_YXQ2 天前
Unity3D中提升AssetBundle加载速度的详细指南
java·spring boot·spring·unity·性能优化·游戏引擎·游戏开发
Miss_SQ2 天前
Unity接入AI—Deepseek,数据流式传输
unity·ai