項目中場景需要一天二十四小時,用到了Time of day插件這裡就不講這個插件的用法了。
Google到一篇文章 http://wiki.unity3d.com/index.php/LightMapSwitcher拿來測試,發現可以用。准備把代碼直接放到項目中發現有個不是問題的問題
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博客中有一個關於動態替換的,大家可以搜索看看。
想各位大神提出意見,看看我的代碼是不是還有什麼問題,或者有改進的地方。