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

Wesley13
• 阅读 547

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