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获取纹理进行加载,代码如下:

/// 
    /// 以IO方式进行加载
    /// 
    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以后有空整理再更新。方便以后查阅。

你可能感兴趣的:(unity)