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 }

 

posted on 2018-09-28 17:16  Roger634  阅读(4089)  评论(0编辑  收藏  举报

导航