Unity3D研究院之Unity5.x运行时动态更新烘培贴图

Unity3D研究院之Unity5.x运行时动态更新烘培贴图(八十七)

前段时间我研究过这个问题,但是没有解决只好作罢。今天刚好有人又问我这个问题,我得空查了一下还是找到了解决办法。另外也感谢问我的人,解答问题的同时也是我学习的过程。

运行时更新烘培贴图分两种情况

1、场景的物件没有发生变化(也就是说没有运行时加载在场景上的Prefab)此时可以直接更换烘培贴图。

usingUnityEngine;
usingSystem.Collections;
 
public class NewBehaviourScript : MonoBehaviour {
 
 //烘培烘培贴图1
 public Texture2DgreenLightMap;
 //烘培贴图2
 public Texture2DredLightMap;
 void OnGUI()
 {
 if(GUILayout.Button("green"))
 {
 LightmapDatadata = new LightmapData();
 data.lightmapFar = greenLightMap;
 LightmapSettings.lightmaps = new LightmapData[1]{data};
 }
 
 if(GUILayout.Button("red"))
 {
 LightmapDatadata = new LightmapData();
 data.lightmapFar = redLightMap;
 LightmapSettings.lightmaps = new LightmapData[1]{data};
 }
 }
}

2.场景的烘培贴图已经更新,但是有些物件prefab想运行时加载进来。如果直接Instance的话 这个Prefab是没有烘培信息的。(灰颜色的)

解决这个问题我查到了 一篇大大的文章,它带了例子大家可以下载下来。 http://forum.unity3d.com/threads/problems-with-instantiating-baked-prefabs.324514/#post-2177524

代码在这里,把如下代码挂在GameObject上。当场景烘培结束后,把他保存成prefab,运行的时候直接加载进来就行了。

usingUnityEngine;
usingSystem.Collections;
usingSystem.Collections.Generic;
 
public class PrefabLightmapData : MonoBehaviour
{
 [System.Serializable]
 struct RendererInfo
 {
 public Rendererrenderer;
 public int lightmapIndex;
 public Vector4lightmapOffsetScale;
 }
 
 [SerializeField]
 RendererInfo[] m_RendererInfo;
 [SerializeField]
 Texture2D[] m_Lightmaps;
 
 void Awake ()
 {
 if (m_RendererInfo == null || m_RendererInfo.Length == 0)
 return;
 
 var lightmaps = LightmapSettings.lightmaps;
 var combinedLightmaps = new LightmapData[lightmaps.Length + m_Lightmaps.Length];
 
 lightmaps.CopyTo(combinedLightmaps, 0);
 for (int i = 0; i < m_Lightmaps.Length;i++)
 {
 combinedLightmaps[i+lightmaps.Length] = new LightmapData();
 combinedLightmaps[i+lightmaps.Length].lightmapFar = m_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];
 info.renderer.lightmapIndex = info.lightmapIndex + lightmapOffsetIndex;
 info.renderer.lightmapScaleOffset = info.lightmapOffsetScale;
 }
 }
 
#if UNITY_EDITOR
 [UnityEditor.MenuItem("Assets/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();
 
 PrefabLightmapData[] prefabs = FindObjectsOfType<PrefabLightmapData>();
 
 foreach (var instancein prefabs)
 {
 var gameObject = instance.gameObject;
 var rendererInfos = new List<RendererInfo>();
 var lightmaps = new List<Texture2D>();
 
 GenerateLightmapInfo(gameObject, rendererInfos, lightmaps);
 
 instance.m_RendererInfo = rendererInfos.ToArray();
 instance.m_Lightmaps = lightmaps.ToArray();
 
 var targetPrefab = UnityEditor.PrefabUtility.GetPrefabParent(gameObject) as GameObject;
 if (targetPrefab != null)
 {
 //UnityEditor.Prefab
 UnityEditor.PrefabUtility.ReplacePrefab(gameObject, targetPrefab);
 }
 }
 }
 
 static void GenerateLightmapInfo (GameObjectroot, List<RendererInfo> rendererInfos, List<Texture2D> lightmaps)
 {
 var renderers = root.GetComponentsInChildren<MeshRenderer>();
 foreach (MeshRendererrendererin renderers)
 {
 if (renderer.lightmapIndex != -1)
 {
 RendererInfoinfo = new RendererInfo();
 info.renderer = renderer;
 info.lightmapOffsetScale = renderer.lightmapScaleOffset;
 
 Texture2Dlightmap = LightmapSettings.lightmaps[renderer.lightmapIndex].lightmapFar;
 
 info.lightmapIndex = lightmaps.IndexOf(lightmap);
 if (info.lightmapIndex == -1)
 {
 info.lightmapIndex = lightmaps.Count;
 lightmaps.Add(lightmap);
 }
 
 rendererInfos.Add(info);
 }
 }
 }
#endif
 
}

点击 Assets/Bake Prefab Lightmaps 进行烘培, 这样它的脚本里会把index 和 offset保存在prefab里。它还会保存上当前烘培场景的Lightmap,如果运行时想更换的话,你可以加一些自己的逻辑进行切换。

最后欢迎大家测试,欢迎大家提出宝贵意见,我们一起把unity这个坑填了!

原文地址:https://www.cnblogs.com/muyouking/p/6647967.html