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 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 }
点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

Unity 2D地面陷阱和死亡特效

一,把陷阱制作成预制体;二,把角色死亡特效制作成预制体三,有一些公共变量要拖进脚本里四,特效要及时的销毁,给特效预制体添加脚本DeadDestroy;五,脚本1,LevelManagerusingSystem.Collections;usingSystem.Collections.Generic;

Cocos Creator中的预制体Prefab

Prefab的用途:为了重复利用!测始预制体,中间丑陋的弹窗为预制体Prefab(https://uploadimages.jianshu.io/upload_images/1496205f5175e982e2cdc07.png?imageMogr2/autoorient/strip%7CimageView2/2/w/1240)

Cocos Creator基础教程(8)—加载预制件

我们上篇讲了\场景切换\(https://my.oschina.net/dannis/blog/3083942"场景切换")并编写了LoadScene场景加组件,这次我们在场景里面创建独立的子界面或子窗口。在CocosCreator中实现子界面的最好方案就是: 预制件。1\.生成预制件CocosCre