在项目中烘焙好的场景贴图资源比较大,这个时候我们也会去进行打包,我用的方法比较粗暴,但是我自己感觉这样用还能够接受,今天抽空码出来,如果有更好的解决方案,当然这个方案就当铺路了。
我主要是新建一个预置体,将我的这些贴图关联到我的这个预置体上,然后把预置体打包,那么解包之后,光照贴图自然就关联到了我的场景中,现在主要是如何将光照贴图关联起来。
1.新建一个空物体,名字自己随便取都行。
2.新建一个脚本挂载到空物体上,主要是用来关联贴图信息的,里面最后一个方法是专门用来添加的,只要点击AddLightmap那么信息就关联好了。
#if UNITY_EDITOR
using UnityEditor;
using System.IO;
#endif
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class PrefabLightmapData : MonoBehaviour {
// Use this for initialization
[System.Serializable]
struct LightMapInfo
{
public Texture2D lightmapFar;
public Texture2D lightmapNear;
}
[SerializeField]
LightMapInfo[] m_LightMapInfo;
void Awake()
{
if(m_LightMapInfo.Length>0)
{
List<LightmapData> list = new List<LightmapData>();
foreach (LightMapInfo info in m_LightMapInfo)
{
LightmapData temp = new LightmapData();
temp.lightmapFar = info.lightmapFar;
temp.lightmapNear = info.lightmapNear;
list.Add(temp);
}
LightmapSettings.lightmaps = list.ToArray();
list.Clear();
}
}
#if UNITY_EDITOR
[MenuItem("Assets/AddInLightmap")]
static void AddInLightMap()
{
PrefabLightmapData temp = FindObjectOfType<PrefabLightmapData>();
temp.m_LightMapInfo = new LightMapInfo[LightmapSettings.lightmaps.Length];
for (int item = 0; item < temp.m_LightMapInfo.Length; ++item)
{
temp.m_LightMapInfo[item].lightmapFar = LightmapSettings.lightmaps[item].lightmapFar;
temp.m_LightMapInfo[item].lightmapNear = LightmapSettings.lightmaps[item].lightmapNear;
}
}
#endif
}
3.还有一些物体引用的mesh都不一样,那么光照贴图的信息也需要一个个关联起来,有一些则已经自动生成xml表的时候已经生成了,创建xml表的前面已经介绍过,这里再写一次。
using UnityEngine;
using UnityEditor;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Xml;
public class CreateSenceElements : EditorWindow
{
// Use this for initialization
[MenuItem("Sence/" + "测试")]
static void CesiElements()
{
GameObject obj_Father = Selection.activeGameObject;
MeshRenderer render = obj_Father.GetComponent<MeshRenderer>();
Debug.Log(render.lightmapIndex + " " + render.lightmapScaleOffset.ToString("0.00000"));
}
[MenuItem("Sence/"+"生成场景元素XML表")]
static void SenceElements()
{
GameObject obj_Father = Selection.activeGameObject;
string filepath = Application.dataPath + "/StreamingAssets" + @"/" + obj_Father.name + ".xml";
//创建XML文档实例
XmlDocument xmlDoc = new XmlDocument();
//创建root节点,也就是最上一层节点
XmlElement root=null;
XmlElement rootSence = null;
XmlElement rootPrefab = null;
if (!File.Exists(filepath))
{
//创建root节点,也就是最上一层节点
root = xmlDoc.CreateElement(obj_Father.name);
rootSence = xmlDoc.CreateElement("SenceElement");
rootPrefab = xmlDoc.CreateElement("SencePrefab");
root.SetAttribute("ID", "ID001");
Debug.Log("createXml OK!");
}
else
{
xmlDoc.Load(filepath);
root = xmlDoc.SelectSingleNode(obj_Father.name) as XmlElement;
rootSence = xmlDoc.SelectSingleNode("SenceElement") as XmlElement;
rootPrefab = xmlDoc.SelectSingleNode("SencePrefab") as XmlElement;
root.RemoveAll();
}
//保存场景中元素的名称
Dictionary<string, int> dicPrefabs = new Dictionary<string, int>();
FindChild(ref xmlDoc, ref rootSence, dicPrefabs, obj_Father.transform, 0);
foreach (string key in dicPrefabs.Keys)
{
XmlElement _ele = xmlDoc.CreateElement("PrefabNode");
_ele.SetAttribute("name", key);
_ele.SetAttribute("num", dicPrefabs[key].ToString());
rootPrefab.AppendChild(_ele);
}
root.AppendChild(rootPrefab);
root.AppendChild(rootSence);
xmlDoc.AppendChild(root);
//把XML文件保存至本地
xmlDoc.Save(filepath);
AssetDatabase.Refresh();
}
static void FindChild(ref XmlDocument doc, ref XmlElement node,Dictionary<string,int> dic, Transform tran ,int level)
{
++level;
foreach (Transform child in tran)
{
XmlElement _ele = doc.CreateElement("SenceNode" + level.ToString());
_ele.SetAttribute("name", child.name);
_ele.SetAttribute("Position", child.localPosition.ToString("0.00"));
_ele.SetAttribute("EulerAngles", child.localEulerAngles.ToString("0.00"));
_ele.SetAttribute("Scale", child.localScale.ToString("0.00"));
MeshFilter _mesh = child.GetComponent<MeshFilter>();
if (_mesh!=null)
{
string _str = _mesh.sharedMesh.name;
_ele.SetAttribute("Prefab", _str);
MeshRenderer _render = child.gameObject.GetComponent<MeshRenderer>();
_ele.SetAttribute("LightMapScale", _render.lightmapScaleOffset.ToString("0.000000"));
_ele.SetAttribute("LightMapIndex", _render.lightmapIndex.ToString());
if (dic.ContainsKey(_str))
{
dic[_str] = dic[_str] + 1;
}
else dic.Add(_str, 1);
}
if (child.childCount >= 1)
{
FindChild(ref doc, ref _ele,dic, child, level);
}
node.AppendChild(_ele);
}
}
}
选中我们的场景,所有的子物体的信息都被保存到了一张表中,现在就要把整体的物体的信息给关联起来,需要在他们身上挂载下面的脚本。
#if UNITY_EDITOR
using UnityEditor;
using System.IO;
#endif
using UnityEngine;
using System.Collections.Generic;
[DisallowMultipleComponent, ExecuteInEditMode]
public class PrefabLightmapDataEditor : MonoBehaviour
{
[System.Serializable]
struct RendererInfo
{
public Renderer renderer;
public int lightmapIndex;
public Vector4 lightmapOffsetScale;
}
[SerializeField]
RendererInfo[] m_RendererInfo;
const string LIGHTMAP_RESOURCE_PATH = "Assets/Resources/Lightmaps/";
[System.Serializable]
struct Texture2D_Remap
{
public int originalLightmapIndex;
public Texture2D originalLightmap;
public Texture2D lightmap0;
public Texture2D lightmap1;
}
static List<Texture2D_Remap> sceneLightmaps = new List<Texture2D_Remap>();
void Start()
{
ApplyRendererInfo();
}
public void ApplyRendererInfo()
{
for (int i = 0; i < m_RendererInfo.Length; i++)
{
var info = m_RendererInfo[i];
info.renderer.lightmapIndex = info.lightmapIndex;
info.renderer.lightmapScaleOffset = info.lightmapOffsetScale;
}
}
#if UNITY_EDITOR
[MenuItem("Assets/Bake Prefab LightmapsEditor")]
static void GenerateLightmapInfoT()
{
Debug.ClearDeveloperConsole();
if (Lightmapping.giWorkflowMode != Lightmapping.GIWorkflowMode.OnDemand)
{
Debug.LogError("ExtractLightmapData requires that you have baked you lightmaps and Auto mode is disabled.");
return;
}
//Lightmapping.Bake();
sceneLightmaps = new List<Texture2D_Remap>();
PrefabLightmapDataEditor[] prefabs = FindObjectsOfType<PrefabLightmapDataEditor>();
foreach (var instance in prefabs)
{
Debug.Log(prefabs.Length);
var gameObject = instance.gameObject;
var rendererInfos = new List<RendererInfo>();
var renderers = gameObject.GetComponentsInChildren<MeshRenderer>();
foreach (MeshRenderer renderer in renderers)
{
if (renderer.lightmapIndex != -1)
{
RendererInfo info = new RendererInfo();
info.renderer = renderer;
info.lightmapOffsetScale = renderer.lightmapScaleOffset;
info.lightmapIndex = renderer.lightmapIndex;
rendererInfos.Add(info);
}
}
instance.m_RendererInfo = rendererInfos.ToArray();
var targetPrefab = PrefabUtility.GetPrefabParent(gameObject) as GameObject;
if (targetPrefab != null)
{
//Prefab
//PrefabUtility.ReplacePrefab(gameObject, targetPrefab);
}
}
Debug.Log("Update to prefab lightmaps finished");
}
#endif
}
点击Bake Prefab LightmapsEditor则可以将贴图的信息全部关联起来,需要注意的是必须是烘焙好的物体,而且身上带有mesh不然会报错。