Unity5.x 动态加载light地图s(烘培贴图)
Unity5.x 动态加载lightmaps(烘培贴图)
项目中场景需要一天二十四小时,用到了Time of day插件这里就不讲这个插件的用法了。
Google到一篇文章 http://wiki.unity3d.com/index.php/LightMapSwitcher拿来测试,发现可以用。准备把代码直接放到项目中发现有个不是问题的问题
这要自己一个一个拖拽,lightmaps少的话还可以,多了就好头疼。
所以我就把代码给改了,可能影响效率,毕竟多执行一些代码,不可避免。不过方便很多。小项目可以用用。
第一个 CC_LightMapSwitch.cs
using UnityEngine; using UnityEditor; using System.Linq; using System.Text; using System.Collections; using System.Collections.Generic; using System.Text.RegularExpressions; //为什么要用[System.Serializable]来序列化,而不是using System然后直接[Serializable] //是应为对下面 <T>as object 有影响 //这里序列化是为了在inspecter面板中可以编辑 [System.Serializable] public class U_P_D{ //存放lightmaps的路径,如我的存放在 Assets下的001文件夹你只需输入001,如果是Assets-Scence-Main,那就输入Scence/Main public string _URL; public string URL{ get {return _URL;} set {_URL=value;} } //后缀名 lightmaps后缀名是 .exr public string _Pattern; public string Pattern{ get {return _Pattern;} set {_Pattern=value;} } //dir 还是 light 即 是远景还是近景 其中dir是lightmapNear,light是lightmapFar public string _Distance; public string Distance{ get {return _Distance;} set {_Distance=value;} } } [System.Serializable] public class ALLNF{ [System.NonSerialized] public Texture2D[] NF; } [System.Serializable] public class AllLightMap{ [System.NonSerialized] public LightmapData[] LM; } public class CC_LightMapSwitcher : MonoBehaviour { //不知道你们遇到过lightmaps之后只有light.exr,没有dir.exr,所以这里我加了个判断 //一切为了懒 public bool _Switchs; public U_P_D[] _UPDs; public List<ALLNF> _AllNFs; public List<AllLightMap> _AllLFs; void Start () { SelectSelf (); //然后将里面的lightmaps排序 for (int i = 0; i < _AllNFs.Count; i++) { _AllNFs[i].NF = _AllNFs[i].NF.OrderBy(t2d => t2d.name, new NaturalSortComparer<string>()).ToArray(); } //如果你打钩表示你的lightmaps有dir和light两种 if (_Switchs) { for (int AllLFs_i = 0; AllLFs_i < _AllLFs.Count; AllLFs_i++) { int AllNFs_i=AllLFs_i*2; _AllLFs[AllLFs_i].LM= new LightmapData[_AllNFs[AllNFs_i].NF.Length]; for (int i=0; i<_AllNFs[AllNFs_i].NF.Length; i++) { _AllLFs[AllLFs_i].LM[i] = new LightmapData(); _AllLFs[AllLFs_i].LM[i].lightmapNear = _AllNFs[AllNFs_i].NF[i]; _AllLFs[AllLFs_i].LM[i].lightmapFar = _AllNFs[AllNFs_i+1].NF[i]; } } } else { for (int AllLFs_i = 0; AllLFs_i < _AllLFs.Count; AllLFs_i++) { //int AllNFs_i=AllLFs_i*2; _AllLFs[AllLFs_i].LM= new LightmapData[_AllNFs[AllLFs_i].NF.Length]; for (int i=0; i<_AllNFs[AllLFs_i].NF.Length; i++) { _AllLFs[AllLFs_i].LM[i] = new LightmapData(); //_AllLFs[AllLFs_i].LM[i].lightmapNear = _AllNFs[AllLFs_i].NF[i]; _AllLFs[AllLFs_i].LM[i].lightmapFar = _AllNFs[AllLFs_i].NF[i]; } } } } #region SelectSelf public void SelectSelf(){ if (_UPDs.Length==_AllNFs.Count) { for (int i = 0; i < _UPDs.Length; i++) { _AllNFs[i].NF=LoadAsset<Texture2D> (_UPDs[i].URL, _UPDs[i].Pattern, _UPDs[i].Distance); } } } T[] LoadAsset<T>(string path, string pattern,string Distance) where T : Object { string objPath = Application.dataPath + "/" + path; string[] directoryEntries; List<T> objList = new List<T>(); try { directoryEntries = System.IO.Directory.GetFileSystemEntries(objPath); for (int i = 0; i < directoryEntries.Length; i++) { string p = directoryEntries[i]; string[] tempPaths = SplitWithString(p, "/Assets/"+path+"\\"); if (tempPaths[1].EndsWith(Distance + "." + pattern)) { if (!tempPaths[1].StartsWith("ReflectionProbe")) { T tempTex = AssetDatabase.LoadAssetAtPath("Assets/"+path+"/" + tempPaths[1], typeof(T)) as T; if (tempTex != null){ objList.Add(tempTex); } } } } } catch (System.IO.DirectoryNotFoundException) { Debug.Log("The path encapsulated in the " + objPath + "Directory object does not exist."); } if (objList.Count > 0) return objList.ToArray(); return null; } public static string[] SplitWithString(string sourceString, string splitString){ string tempSourceString = sourceString; List<string> arrayList = new List<string>(); string s = string.Empty; while (sourceString.IndexOf(splitString) > -1) //切割 { s = sourceString.Substring(0, sourceString.IndexOf(splitString)); sourceString = sourceString.Substring(sourceString.IndexOf(splitString) + splitString.Length); arrayList.Add(s); } arrayList.Add(sourceString); return arrayList.ToArray(); } #endregion #region Publics public void SetToDay() { //这里与源代码不同 LightmapSettings.lightmaps = _AllLFs[0].LM; } public void SetToNight() { LightmapSettings.lightmaps = _AllLFs[1].LM; } #endregion #region Debug [ContextMenu ("Set to Night")] void Debug00() { SetToNight(); } [ContextMenu ("Set to Day")] void Debug01() { SetToDay(); } #endregion }
第二个 NaturalSortComparer.cs 这个没变
using UnityEngine; using System.Collections; using System; using System.Collections.Generic; using System.Text.RegularExpressions; public class NaturalSortComparer<T> : IComparer<string>, IDisposable { private readonly bool isAscending; public NaturalSortComparer(bool inAscendingOrder = true) { this.isAscending = inAscendingOrder; } #region IComparer<string> Members public int Compare(string x, string y) { throw new NotImplementedException(); } #endregion #region IComparer<string> Members int IComparer<string>.Compare(string x, string y) { if (x == y) return 0; string[] x1, y1; if (!table.TryGetValue(x, out x1)) { x1 = Regex.Split(x.Replace(" ", ""), "([0-9]+)"); table.Add(x, x1); } if (!table.TryGetValue(y, out y1)) { y1 = Regex.Split(y.Replace(" ", ""), "([0-9]+)"); table.Add(y, y1); } int returnVal; for (int i = 0; i < x1.Length && i < y1.Length; i++) { if (x1[i] != y1[i]) { returnVal = PartCompare(x1[i], y1[i]); return isAscending ? returnVal : -returnVal; } } if (y1.Length > x1.Length) { returnVal = 1; } else if (x1.Length > y1.Length) { returnVal = -1; } else { returnVal = 0; } return isAscending ? returnVal : -returnVal; } private static int PartCompare(string left, string right) { int x, y; if (!int.TryParse(left, out x)) return left.CompareTo(right); if (!int.TryParse(right, out y)) return left.CompareTo(right); return x.CompareTo(y); } #endregion private Dictionary<string, string[]> table = new Dictionary<string, string[]>(); public void Dispose() { table.Clear(); table = null; } }
用法 顺序反着说好理解
1.Switchs打钩就是有dir和light ,只有一种就取消
2.AllLFs 表示你有几套贴图,我这只用到两套白天黑夜,可以多套,下面就要相对应的改变参数
3.AllNFs 和UPDs长度一致 如果Switchs打钩 表示AllLFS一套中有分近景和远景两种,长度就是AllLFS的两倍。Switchs不打钩,长度与AllLFS一致。
4.UPDs 中URL表示lightmaps路径
Pattern为后缀名
Distance为远近景
代码有注释
亲测可用。因为我这里只是用到两套贴图,所以点击事件就写的白天和黑夜两种,如果贴图有十多套完全可以代码控制。这里就不写了。
还有这个代码适合静态场景物体贴图替换,场景动态物体中贴图替换现在没考虑。 不过我看到雨松MOMO博客中有一个关于动态替换的,大家可以搜索看看。
想各位大神提出意见,看看我的代码是不是还有什么问题,或者有改进的地方。