Unity 预制体烘焙光影丢失,Unity2018 预制嵌套

Wesley13
• 阅读 710

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 }
点赞
收藏
评论区
推荐文章
blmius blmius
3年前
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
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Wesley13 Wesley13
3年前
Unity 2D地面陷阱和死亡特效
一,把陷阱制作成预制体;二,把角色死亡特效制作成预制体三,有一些公共变量要拖进脚本里四,特效要及时的销毁,给特效预制体添加脚本DeadDestroy;五,脚本1,LevelManagerusingSystem.Collections;usingSystem.Collections.Generic;
Stella981 Stella981
3年前
Cocos Creator中的预制体Prefab
Prefab的用途:为了重复利用!测始预制体,中间丑陋的弹窗为预制体Prefab(https://uploadimages.jianshu.io/upload_images/1496205f5175e982e2cdc07.png?imageMogr2/autoorient/strip%7CimageView2/2/w/1240)
Stella981 Stella981
3年前
Cocos Creator基础教程(8)—加载预制件
我们上篇讲了\场景切换\(https://my.oschina.net/dannis/blog/3083942"场景切换")并编写了LoadScene场景加组件,这次我们在场景里面创建独立的子界面或子窗口。在CocosCreator中实现子界面的最好方案就是: 预制件。1\.生成预制件CocosCre
Stella981 Stella981
3年前
Creator避免UI一次性加入场景
      通过层级管理器,做出来的UI,一次性放到场景里,加载无用的资源太多了,会导致加载速度慢,浪费内存,使用预制资源,一开始不使用的资源,使用预制资源,需要的时候加载进来,不需要的时候移除掉。      下图是实现的效果图,功能很简单,只为了实现原理。!(https://oscimg.oschina.net/oscnet/2d
Wesley13 Wesley13
3年前
Unity基础系列(二)——构建一个视图(可视化数学)
!(https://oscimg.oschina.net/oscnet/0c9eebcbcf64460b6496058c8c9cc117945.png)点击蓝字关注我们吧!目录1创建一排立方体1.1预制体1.2视图组件1.3实例化组件1.4代码循环1.5简化语法1.6改变域1.7把向量挪出循环1
Stella981 Stella981
3年前
Cocos Creator导出场景和预制的问题
CocosCreator支持导出当前项目中的场景和预制为另一个项目所用:1,选择要导出的场景或者预制;2,选择要导出到的目标文件夹位置并进行可能的重新命名;3,导出一个压缩文件.zip。4,解压压缩文件.zip,然后可以拖动其中的内容到目标项目指定位置进行使用即可。但是也有一些小问题:1,
预制菜火了,如何选择预制菜品牌呢?
如今,即使被称为“日不落”的餐饮业,也在使尽浑身解数满足社会发展需求。因此,“预制菜”应运而生,成为近年来的行业热点。预制菜怎么就火了呢?大体可以从以下几个方面来说。一、首先,懒宅经济助推了预制菜行业高速发展,其给出的数据显示,消费预制菜的目的,排在
Python进阶者 Python进阶者
10个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这