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 }