Unity 预制体烘焙光影丢失,Unity2018 预制嵌套
Unity2018.3测试版发布后支持预制体嵌套……
问题:
1.unity场景烘焙后,再制作预制体后烘焙的光影丢失
2.如何将预制体的更改应用到各个子预制体
解决:
1.这个问题官方有解决,即是给每个需要加载的prefab添加PrefabLightmapData.cs脚本,但是这个脚本没有写完整,它只能在Non-Directional模式下可以正常工作,即没有加载Lightmap-_dir灯光贴图
2.在有嵌套的prefabs中,首先打开嵌套prefabs然后对各个子prefab执行applyAll操作,最后重新保存整个嵌套prefabs
3.本代码是在Unity2018.3.b3版本下编写的,部分api老版本有可能不一样(修改一下即可)
在官方代码基础上修改的代码如下:
1 using System.Collections; 2 using System.Collections.Generic; 3 using System.IO; 4 using UnityEditor; 5 using UnityEngine; 6 using VR403Works.Foundation.Extentions; 7 8 [DisallowMultipleComponent] 9 [ExecuteInEditMode] 10 public class PrefabLightmapData : MonoBehaviour 11 { 12 13 [System.Serializable] 14 struct RendererInfo 15 { 16 public Renderer renderer; 17 public int lightmapIndex; 18 public Vector4 lightmapOffsetScale; 19 } 20 21 [SerializeField] 22 RendererInfo[] m_RendererInfo; 23 [SerializeField] 24 Texture2D[] m_LightmapsColor; 25 [SerializeField] 26 Texture2D[] _lightmapsDir; 27 28 void Awake() 29 { 30 if (m_RendererInfo == null || m_RendererInfo.Length == 0) 31 return; 32 33 var lightmaps = LightmapSettings.lightmaps; 34 var combinedLightmaps = new LightmapData[lightmaps.Length + m_LightmapsColor.Length]; 35 36 lightmaps.CopyTo(combinedLightmaps, 0); 37 for (int i = 0; i < m_LightmapsColor.Length; i++) 38 { 39 combinedLightmaps[i + lightmaps.Length] = new LightmapData(); 40 combinedLightmaps[i + lightmaps.Length].lightmapColor = m_LightmapsColor[i]; 41 combinedLightmaps[i + lightmaps.Length].lightmapDir = _lightmapsDir[i]; 42 43 } 44 45 ApplyRendererInfo(m_RendererInfo, lightmaps.Length); 46 LightmapSettings.lightmaps = combinedLightmaps; 47 } 48 49 50 static void ApplyRendererInfo(RendererInfo[] infos, int lightmapOffsetIndex) 51 { 52 for (int i = 0; i < infos.Length; i++) 53 { 54 var info = infos[i]; 55 if (info.renderer != null) 56 { 57 info.renderer.lightmapIndex = info.lightmapIndex + lightmapOffsetIndex; 58 info.renderer.lightmapScaleOffset = info.lightmapOffsetScale; 59 } 60 } 61 } 62 63 #if UNITY_EDITOR 64 [UnityEditor.MenuItem("VR403WorksTools/Bake Prefab Lightmaps")] 65 static void GenerateLightmapInfo() 66 { 67 if (UnityEditor.Lightmapping.giWorkflowMode != UnityEditor.Lightmapping.GIWorkflowMode.OnDemand) 68 { 69 Debug.LogError("ExtractLightmapData requires that you have baked you lightmaps and Auto mode is disabled."); 70 return; 71 } 72 UnityEditor.Lightmapping.Bake(); 73 74 PrefabLightmapData[] prefabs = GameObject.FindObjectsOfType<PrefabLightmapData>(); 75 76 foreach (var instance in prefabs) 77 { 78 var gameObject = instance.gameObject; 79 var rendererInfos = new List<RendererInfo>(); 80 var lightmapsColor = new List<Texture2D>(); 81 List<Texture2D> lightmapsDir = new List<Texture2D>(); 82 83 GenerateLightmapInfo(gameObject, rendererInfos, lightmapsColor, lightmapsDir); 84 85 instance.m_RendererInfo = rendererInfos.ToArray(); 86 instance.m_LightmapsColor = lightmapsColor.ToArray(); 87 instance._lightmapsDir = lightmapsDir.ToArray(); 88 89 90 var targetPrefab = PrefabUtility.GetCorrespondingObjectFromOriginalSource(instance.gameObject) as GameObject; 91 if (targetPrefab != null) 92 { 93 GameObject root = PrefabUtility.GetOutermostPrefabInstanceRoot(instance.gameObject); // 根结点 94 //如果当前预制体是是某个嵌套预制体的一部分(IsPartOfPrefabInstance) 95 if (root != null) 96 { 97 GameObject rootPrefab = PrefabUtility.GetCorrespondingObjectFromSource(instance.gameObject); 98 string rootPath = AssetDatabase.GetAssetPath(rootPrefab); 99 //打开根部预制体 100 PrefabUtility.UnpackPrefabInstanceAndReturnNewOutermostRoots(root, PrefabUnpackMode.OutermostRoot); 101 try 102 { 103 //Apply各个子预制体的改变 104 PrefabUtility.ApplyPrefabInstance(instance.gameObject, InteractionMode.AutomatedAction); 105 } 106 catch { } 107 finally 108 { 109 //重新更新根预制体 110 PrefabUtility.SaveAsPrefabAssetAndConnect(root, rootPath, InteractionMode.AutomatedAction); 111 } 112 } 113 else 114 { 115 PrefabUtility.ApplyPrefabInstance(instance.gameObject, InteractionMode.AutomatedAction); 116 } 117 } 118 } 119 } 120 121 static void GenerateLightmapInfo(GameObject root, List<RendererInfo> rendererInfos, List<Texture2D> lightmapsColor, List<Texture2D> lightmapsDir) 122 { 123 var renderers = root.GetComponentsInChildren<MeshRenderer>(); 124 foreach (MeshRenderer renderer in renderers) 125 { 126 if (renderer.lightmapIndex != -1) 127 { 128 RendererInfo info = new RendererInfo(); 129 info.renderer = renderer; 130 if (renderer.lightmapScaleOffset != Vector4.zero) 131 { 132 info.lightmapOffsetScale = renderer.lightmapScaleOffset; 133 Texture2D lightmapColor = LightmapSettings.lightmaps[renderer.lightmapIndex].lightmapColor; 134 Texture2D lightmapDir = LightmapSettings.lightmaps[renderer.lightmapIndex].lightmapDir; 135 136 info.lightmapIndex = lightmapsColor.IndexOf(lightmapColor); 137 if (info.lightmapIndex == -1) 138 { 139 info.lightmapIndex = lightmapsColor.Count; 140 lightmapsColor.Add(lightmapColor); 141 lightmapsDir.Add(lightmapDir); 142 } 143 144 rendererInfos.Add(info); 145 } 146 147 } 148 } 149 } 150 #endif 151 }