Unity5.x 动态加载light地图s(烘培贴图)

Unity5.x 动态加载lightmaps(烘培贴图)

项目中场景需要一天二十四小时,用到了Time of day插件这里就不讲这个插件的用法了。

Google到一篇文章 http://wiki.unity3d.com/index.php/LightMapSwitcher拿来测试,发现可以用。准备把代码直接放到项目中发现有个不是问题的问题

 Unity5.x 动态加载light地图s(烘培贴图)

这要自己一个一个拖拽,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为远近景

代码有注释

 Unity5.x 动态加载light地图s(烘培贴图)

亲测可用。因为我这里只是用到两套贴图,所以点击事件就写的白天和黑夜两种,如果贴图有十多套完全可以代码控制。这里就不写了。

还有这个代码适合静态场景物体贴图替换,场景动态物体中贴图替换现在没考虑。 不过我看到雨松MOMO博客中有一个关于动态替换的,大家可以搜索看看。

 

想各位大神提出意见,看看我的代码是不是还有什么问题,或者有改进的地方。