1. 程式人生 > >unity Editor自動生成材質及動態載入資源

unity Editor自動生成材質及動態載入資源

最近這兩天在做一個專案,然後裡面有六十多個素材,還要全部生成材質球,差點人都廢了,然後去手冊上著了一下可以自動生成材質球的程式碼。然後自動生成材質球的過程中我還想要給材質球賦予一個預設的漫反射貼圖,貼圖是從網上下載來的,踩了數不清的坑之後終於搞定了。
直接貼程式碼

   // Use this for initialization
    void Start()
    {
        StartCoroutine(DownLoadFiles());
    }

 public IEnumerator DownLoadFiles()
    {
        //使用UnityWebRequest下載紋理
        using (UnityWebRequest www = UnityWebRequest.GetTexture
("http://pic1.16pic.com/00/04/57/16pic_457578_b.jpg")) { yield return www.Send(); if (www.isError) { Debug.Log(www.error); } else { Debug.Log(www.downloadHandler.data.Length); try { FileInfo fi = new FileInfo("Assets/Pictures/image.png"
); if (!fi.Exists) { //如果檔案不存在 建立檔案 Stream outStream = fi.Create(); //將下載的資料儲存到本地檔案 outStream.Write(www.downloadHandler.data, 0, www.downloadHandler.data.Length); //關閉檔案流 outStream.Close
(); //資源重新整理 這句一定要加 不然的話雖然資料夾下有該檔案,但是檔案並沒有被加入到專案工程裡 AssetDatabase.Refresh(); } //獲取到該紋理檔案 Texture myTexture = AssetDatabase.LoadAssetAtPath("Assets/Pictures/image.png", typeof(Texture2D)) as Texture2D; Debug.Log("下載成功"); //下面是自動將改圖片生成材質球 //穿件材質球 Material material = new Material(Shader.Find("Standard")); //將之前儲存好的紋理賦值給材質球 material.mainTexture = myTexture; //儲存材質球 AssetDatabase.CreateAsset(material, "/Material/image.mat"); AssetDatabase.Refresh(); } catch (Exception e) { Debug.Log(e.Message); Debug.Log("下載失敗"); } } } }

UnityWebRequest 這個類是Unity對WWW一種封裝。裡面提供了一系列的方法。使用UnityWebRequest方法進行網路請求。然後得到返回的資料。最後建立一個檔案,放在資料夾裡面。 AssetDatabase.Refresh();這句話是一定要加的,不加會使得編輯器中沒有改貼圖,那麼最後建立的材質球會沒有預設貼圖。最後使用AssetDatabase.CreateAsset方法進行建立一個材質球。
在重新整理匯入貼圖的時候,預設的貼圖型別是texture2D型別,如果想要修改型別,那麼在Editor資料夾下新增一個檔案,裡面新增程式碼如下:

public class TransImageType : AssetPostprocessor
{

    void OnPreprocessTexture()
    {

        Debug.Log("OnPreprocessTexture");
        //自動設定型別;  
        TextureImporter textureImporter = (TextureImporter)assetImporter;
        textureImporter.textureType = TextureImporterType.Image;

    }
}

TextureImporterType對應的type型別可以在網上查詢到。上述該方法將UnityWebRequest.GetTexture修改為UnityWebRequest.Get,可以在編輯器狀態下新增任意新的檔案。但是需要保證該資料夾必須存在,不存在會報找不到路徑的錯誤。

上述該方法只能在編輯器模式下執行,如果程式已經發布,那麼如果使用外部資源就需要新的方法。在網上翻閱了N多資源之後,其中
http://www.cnblogs.com/murongxiaopifu/p/4199541.html?utm_source=tuicool&utm_medium=referral
這篇文章給了我很大得幫助,然後我對程式碼進行了修改,外部讀取圖片有兩種方式,一種是使用WWW方法來進行載入,另一種方法是使用流方法來載入檔案,unity提供了使用外部紋理資源的介面,先要將資源下載到目的資料夾下,程式碼如下:

    public IEnumerator DownLoadFiles()
    {
        //使用UnityWebRequest下載紋理
        using (UnityWebRequest www = UnityWebRequest.GetTexture("http://pic1.16pic.com/00/04/57/16pic_457578_b.jpg")) { 
            yield return www.Send();
        if (www.isError)
        {
            Debug.Log(www.error);
        }
        else
        {
            Debug.Log(www.downloadHandler.data.Length);
            try
            {
                FileInfo fi = new FileInfo(Application.persistentDataPath+"/image.png");
                if (!fi.Exists)
                {

                    //如果檔案不存在   建立檔案
                    Stream outStream = fi.Create();
                    //將下載的資料儲存到本地檔案
                    outStream.Write(www.downloadHandler.data, 0, www.downloadHandler.data.Length);
                    //關閉檔案流
                    outStream.Close();
                    //資源重新整理   這句一定要加  不然的話雖然資料夾下有該檔案,但是檔案並沒有被加入到專案工程裡
                }


                    sPath = "file:///" + Application.persistentDataPath + "/image.png";
                    Debug.Log("下載成功");
                    print(sPath);

            }
            catch (Exception e)
            {
                Debug.Log(e.Message);
                Debug.Log("下載失敗");
            }
            }

        }
    }

將圖片下載成功後,有兩個首先是原始的IO獲取紋理進行載入,程式碼如下:

/// <summary>
    /// 以IO方式進行載入
    /// </summary>
    private void LoadTextureByIO()
    {
        double startTime = (double)Time.time;
        //建立檔案讀取流
        FileStream fileStream = new FileStream(Application.persistentDataPath + "/image.png", FileMode.Open, FileAccess.Read);
        fileStream.Seek(0, SeekOrigin.Begin);
        //建立檔案長度緩衝區
        byte[] bytes = new byte[fileStream.Length];
        //讀取檔案
        fileStream.Read(bytes, 0, (int)fileStream.Length);
        //釋放檔案讀取流
        fileStream.Close();
        fileStream.Dispose();
        fileStream = null;

        //建立Texture
        int width = 300;
        int height = 372;
        Texture2D texture = new Texture2D(width, height);
        texture.LoadImage(bytes);
       //下面程式碼是使用紋理做任何你要實現的功能
       ...
    }

還有一種載入的方式是使用Unity的方法進行獲取紋理,程式碼如下:

 private IEnumerator LoadTextureByWWW() {
        using (WWW w = new WWW("file:///" + Application.persistentDataPath + "/image.png")) 
        {
            yield return w;
            Texture2D tex = w.texture;
            //下面程式碼是使用紋理做任何你要實現的功能
       ...
        }
    }

上面程式碼有一個需要特別注意的點就是file後面一定要跟上三個/,如果你寫的是兩個/,那麼WWW在讀取本地資源的時候路徑會出現問題,碟符會丟失,因為看不到unity的原始碼,所以我也不知道底層是怎麼處理的,這裡是一個大坑,然後可以使用tex來進行你需要實現的功能。例子Demo以後有空整理再更新。方便以後查閱。