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 1 using System.Collections; 2 2 using System.Collections.Generic; 3 3 using System.IO; 4 4 using UnityEditor; 5 5 using UnityEngine; 6 6 using VR403Works.Foundation.Extentions; 7 7 8 8 [DisallowMultipleComponent] 9 9 [ExecuteInEditMode] 10 10 public class PrefabLightmapData : MonoBehaviour 11 11 { 12 12 13 13 [System.Serializable] 14 14 struct RendererInfo 15 15 { 16 16 public Renderer renderer; 17 17 public int lightmapIndex; 18 18 public Vector4 lightmapOffsetScale; 19 19 } 20 20 21 21 [SerializeField] 22 22 RendererInfo[] m_RendererInfo; 23 23 [SerializeField] 24 24 Texture2D[] m_LightmapsColor; 25 25 [SerializeField] 26 26 Texture2D[] _lightmapsDir; 27 27 28 28 void Awake() 29 29 { 30 30 if (m_RendererInfo == null || m_RendererInfo.Length == 0) 31 31 return; 32 32 33 33 var lightmaps = LightmapSettings.lightmaps; 34 34 var combinedLightmaps = new LightmapData[lightmaps.Length + m_LightmapsColor.Length]; 35 35 36 36 lightmaps.CopyTo(combinedLightmaps, 0); 37 37 for (int i = 0; i < m_LightmapsColor.Length; i++) 38 38 { 39 39 combinedLightmaps[i + lightmaps.Length] = new LightmapData(); 40 40 combinedLightmaps[i + lightmaps.Length].lightmapColor = m_LightmapsColor[i]; 41 41 combinedLightmaps[i + lightmaps.Length].lightmapDir = _lightmapsDir[i]; 42 42 43 43 } 44 44 45 45 ApplyRendererInfo(m_RendererInfo, lightmaps.Length); 46 46 LightmapSettings.lightmaps = combinedLightmaps; 47 47 } 48 48 49 49 50 50 static void ApplyRendererInfo(RendererInfo[] infos, int lightmapOffsetIndex) 51 51 { 52 52 for (int i = 0; i < infos.Length; i++) 53 53 { 54 54 var info = infos[i]; 55 55 if (info.renderer != null) 56 56 { 57 57 info.renderer.lightmapIndex = info.lightmapIndex + lightmapOffsetIndex; 58 58 info.renderer.lightmapScaleOffset = info.lightmapOffsetScale; 59 59 } 60 60 } 61 61 } 62 62 63 63 #if UNITY_EDITOR 64 64 [UnityEditor.MenuItem("VR403WorksTools/Bake Prefab Lightmaps")] 65 65 static void GenerateLightmapInfo() 66 66 { 67 67 if (UnityEditor.Lightmapping.giWorkflowMode != UnityEditor.Lightmapping.GIWorkflowMode.OnDemand) 68 68 { 69 69 Debug.LogError("ExtractLightmapData requires that you have baked you lightmaps and Auto mode is disabled."); 70 70 return; 71 71 } 72 72 UnityEditor.Lightmapping.Bake(); 73 73 74 74 PrefabLightmapData[] prefabs = GameObject.FindObjectsOfType<PrefabLightmapData>(); 75 75 76 76 foreach (var instance in prefabs) 77 77 { 78 78 var gameObject = instance.gameObject; 79 79 var rendererInfos = new List<RendererInfo>(); 80 80 var lightmapsColor = new List<Texture2D>(); 81 81 List<Texture2D> lightmapsDir = new List<Texture2D>(); 82 82 83 83 GenerateLightmapInfo(gameObject, rendererInfos, lightmapsColor, lightmapsDir); 84 84 85 85 instance.m_RendererInfo = rendererInfos.ToArray(); 86 86 instance.m_LightmapsColor = lightmapsColor.ToArray(); 87 87 instance._lightmapsDir = lightmapsDir.ToArray(); 88 88 89 89 90 90 var targetPrefab = PrefabUtility.GetCorrespondingObjectFromOriginalSource(instance.gameObject) as GameObject; 91 91 if (targetPrefab != null) 92 92 { 93 93 GameObject root = PrefabUtility.GetOutermostPrefabInstanceRoot(instance.gameObject); // 根结点 94 94 //如果当前预制体是是某个嵌套预制体的一部分(IsPartOfPrefabInstance) 95 95 if (root != null) 96 96 { 97 97 GameObject rootPrefab = PrefabUtility.GetCorrespondingObjectFromSource(instance.gameObject); 98 98 string rootPath = AssetDatabase.GetAssetPath(rootPrefab); 99 99 //打开根部预制体 100100 PrefabUtility.UnpackPrefabInstanceAndReturnNewOutermostRoots(root, PrefabUnpackMode.OutermostRoot); 101101 try 102102 { 103103 //Apply各个子预制体的改变 104104 PrefabUtility.ApplyPrefabInstance(instance.gameObject, InteractionMode.AutomatedAction); 105105 } 106106 catch { } 107107 finally 108108 { 109109 //重新更新根预制体 110110 PrefabUtility.SaveAsPrefabAssetAndConnect(root, rootPath, InteractionMode.AutomatedAction); 111111 } 112112 } 113113 else 114114 { 115115 PrefabUtility.ApplyPrefabInstance(instance.gameObject, InteractionMode.AutomatedAction); 116116 } 117117 } 118118 } 119119 } 120120 121121 static void GenerateLightmapInfo(GameObject root, List<RendererInfo> rendererInfos, List<Texture2D> lightmapsColor, List<Texture2D> lightmapsDir) 122122 { 123123 var renderers = root.GetComponentsInChildren<MeshRenderer>(); 124124 foreach (MeshRenderer renderer in renderers) 125125 { 126126 if (renderer.lightmapIndex != -1) 127127 { 128128 RendererInfo info = new RendererInfo(); 129129 info.renderer = renderer; 130130 if (renderer.lightmapScaleOffset != Vector4.zero) 131131 { 132132 info.lightmapOffsetScale = renderer.lightmapScaleOffset; 133133 Texture2D lightmapColor = LightmapSettings.lightmaps[renderer.lightmapIndex].lightmapColor; 134134 Texture2D lightmapDir = LightmapSettings.lightmaps[renderer.lightmapIndex].lightmapDir; 135135 136136 info.lightmapIndex = lightmapsColor.IndexOf(lightmapColor); 137137 if (info.lightmapIndex == -1) 138138 { 139139 info.lightmapIndex = lightmapsColor.Count; 140140 lightmapsColor.Add(lightmapColor); 141141 lightmapsDir.Add(lightmapDir); 142142 } 143143 144144 rendererInfos.Add(info); 145145 } 146146 147147 } 148148 } 149149 } 150150 #endif 151151 }