unity版本為2021.8
預制體不能攜帶光照貼圖信息,只能我們自己準備了
多方查找加自己摸索終于找到了適合新版本的解決方案,直接貼代碼
將這個腳本掛到預制體的最上級
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;[System.Serializable]
public struct RendererInfo
{public Renderer renderer;//網格物體 網格和地形的光照信息是分開的public Terrain terrain;//地形public int lightmapIndex;public Vector4 lightmapScaleScaleOffset;
}
//記錄光照貼圖的信息
public class PrefabLightmapData : MonoBehaviour
{public RendererInfo[] m_RendererInfo;public Texture2D[] m_Lightmaps_light;//顏色貼圖public Texture2D[] m_Lightmaps_dir;//方向貼圖public Texture2D[] m_Lightmaps_shadowmask;//陰影貼圖private void Awake() {RebuildLight();}public void RebuildLight(){if (m_RendererInfo == null || m_RendererInfo.Length == 0) return;LightmapData[] lightmapDataArray = new LightmapData[m_Lightmaps_light.Length];for (int i = 0; i < m_Lightmaps_light.Length; i++){LightmapData lightmapData = new LightmapData();if (i < m_Lightmaps_light.Length) lightmapData.lightmapColor = m_Lightmaps_light[i];if (i < m_Lightmaps_dir.Length) lightmapData.lightmapDir = m_Lightmaps_dir[i];if (i < m_Lightmaps_shadowmask.Length) lightmapData.shadowMask = m_Lightmaps_shadowmask[i];lightmapDataArray[i] = lightmapData;}//為預制體的物體應用光照貼圖ApplyRendererInfo(m_RendererInfo);LightmapSettings.lightmaps = lightmapDataArray;//將光照貼圖應用到Untiy}//應用光照貼圖信息到重建的預制體private void ApplyRendererInfo(RendererInfo[] rendererInfoArray){for (int i = 0; i < rendererInfoArray.Length; i++){RendererInfo rendererInfo = rendererInfoArray[i];if (rendererInfo.renderer != null){rendererInfo.renderer.lightmapIndex = rendererInfo.lightmapIndex;rendererInfo.renderer.lightmapScaleOffset = rendererInfo.lightmapScaleScaleOffset;}else if (rendererInfo.terrain != null){rendererInfo.terrain.lightmapIndex = rendererInfo.lightmapIndex;rendererInfo.terrain.lightmapScaleOffset = rendererInfo.lightmapScaleScaleOffset;}}}
}
//自定義inspector面板
[CustomEditor(typeof(PrefabLightmapData))]
public class PrefabLightmapData_Inspector : Editor
{//重寫OnInspectorGUI類(刷新Inspector面板)public override void OnInspectorGUI(){//繼承基類方法base.OnInspectorGUI();PrefabLightmapData myScript = (PrefabLightmapData)target;//繪制ButtonRect rect = new Rect(0, 0,100,50);if (GUILayout.Button("重新構建烘焙光照")){myScript.RebuildLight();}}
}
在使用下方的腳本完成烘焙后,腳本將自動記錄所有模型和地形的烘焙信息,并在運行后自動重建光照貼圖,如果我們需要在不運行時查看光照貼圖效果,可以手動點擊“重新構建烘焙光照”的按鈕
重寫烘焙,烘焙完成后自動準備重建光照貼圖所需要的信息
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public static class BackeLightMap
{[UnityEditor.MenuItem("Tools/光照/烘焙光照貼圖")]private 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();//找到有這個腳本的物體PrefabLightmapData[] prefabs = Object.FindObjectsOfType<PrefabLightmapData>();foreach (var prefabInScene in prefabs){GameObject scenePrefab = prefabInScene.gameObject;List<RendererInfo> rendererInfos = new List<RendererInfo>();//重建光照貼圖時需要的信息List<Texture2D> lightmaps_light = new List<Texture2D>();//所有的光照貼圖List<Texture2D> lightmaps_dir = new List<Texture2D>();//所有的光照貼圖List<Texture2D> lightmaps_shadowmask = new List<Texture2D>();//所有的光照貼圖GenerateLightmapInfo(scenePrefab, rendererInfos, lightmaps_light, lightmaps_dir, lightmaps_shadowmask);//獲取當前物體的光照貼圖信息和光照貼圖//為光照貼圖信息和光照貼圖賦值prefabInScene.m_RendererInfo = rendererInfos.ToArray();prefabInScene.m_Lightmaps_light = lightmaps_light.ToArray();prefabInScene.m_Lightmaps_dir = lightmaps_dir.ToArray();prefabInScene.m_Lightmaps_shadowmask = lightmaps_shadowmask.ToArray();//替換掉已經保存的預制體GameObject sourcePrefab = UnityEditor.PrefabUtility.GetPrefabParent(prefabInScene) as GameObject;//GameObject sourcePrefab = UnityEditor.PrefabUtility.GetCorrespondingObjectFromSource(scenePrefab);if (sourcePrefab != null){UnityEditor.PrefabUtility.ReplacePrefab(scenePrefab, sourcePrefab);}}}//點擊按鈕生成光照貼圖信息private static void GenerateLightmapInfo(GameObject root, List<RendererInfo> rendererInfoList, List<Texture2D> lightmaps_light, List<Texture2D> lightmaps_dir, List<Texture2D> lightmaps_shadowmask){//找到這個物體的所有網格MeshRenderer[] renderers = root.GetComponentsInChildren<MeshRenderer>();//遍歷網格foreach (MeshRenderer meshRenderer in renderers){if (meshRenderer.lightmapIndex != -1){//收集光照貼圖信息RendererInfo rendererInfo = new RendererInfo();rendererInfo.renderer = meshRenderer;rendererInfo.lightmapIndex = meshRenderer.lightmapIndex;rendererInfo.lightmapScaleScaleOffset = meshRenderer.lightmapScaleOffset;//收集光照貼圖//顏色貼圖Texture2D lightmap_light = LightmapSettings.lightmaps[meshRenderer.lightmapIndex].lightmapColor;AddLightMapToCheach(lightmaps_light, lightmap_light);//方向貼圖Texture2D lightmap_dir = LightmapSettings.lightmaps[meshRenderer.lightmapIndex].lightmapDir;AddLightMapToCheach(lightmaps_dir, lightmap_dir);//shadowmaskTexture2D lightmap_shadowmask = LightmapSettings.lightmaps[meshRenderer.lightmapIndex].shadowMask;AddLightMapToCheach(lightmaps_shadowmask,lightmap_shadowmask);//光照信息rendererInfoList.Add(rendererInfo);}}//找到這個物體的所有網格Terrain[] terrains = root.GetComponentsInChildren<Terrain>();//遍歷網格foreach (Terrain terrain in terrains){if (terrain.lightmapIndex != -1){//收集光照貼圖信息RendererInfo rendererInfo = new RendererInfo();rendererInfo.terrain = terrain;rendererInfo.lightmapIndex = terrain.lightmapIndex;rendererInfo.lightmapScaleScaleOffset = terrain.lightmapScaleOffset;//收集光照貼圖//顏色貼圖Texture2D lightmap_light = LightmapSettings.lightmaps[terrain.lightmapIndex].lightmapColor;AddLightMapToCheach(lightmaps_light, lightmap_light);//方向貼圖Texture2D lightmap_dir = LightmapSettings.lightmaps[terrain.lightmapIndex].lightmapDir;AddLightMapToCheach(lightmaps_dir, lightmap_dir);//shadowmaskTexture2D lightmap_shadowmask = LightmapSettings.lightmaps[terrain.lightmapIndex].shadowMask;AddLightMapToCheach(lightmaps_shadowmask, lightmap_shadowmask);//光照信息rendererInfoList.Add(rendererInfo);}}}//將一個光照貼圖添加進緩存private static void AddLightMapToCheach(List<Texture2D> list,Texture2D texture){if (texture == null) return;int index = list.IndexOf(texture);//查找已有的集合里有沒有這個元素,如果沒有,返回-1if (index == -1){list.Add(texture);}}
}
工具欄里會出現烘焙按鈕,點擊烘焙光照貼圖,不要再用Unity自己的烘焙了,為場景中所有掛載了PrefabLightmapData 的預制體烘焙光照