unity编辑器拓展一——删除项目工程里的未使用Shader

来源:互联网 发布:seo优缺点 编辑:程序博客网 时间:2024/05/16 12:23

1.描述

  我们在做项目的时候,美术会放很多shader在项目中,有一部分是没有用到的,想删又怕删错,会导致一些材质球丢shader,显示紫色。

今天就来想办法把多余的shader删干净。

2.分析

  在写代码之前,先分析下思路。首先我们要分析shader会被哪些文件引用,我找到了下面的两种情况。

1.material 这种情况是最常规的,所有用到的材质球都会依赖自己的shader

2.scene 这种情况不多,但是也会有,一般是屏幕特效之类的东西,在相机上挂了一个脚本,然后脚本里面挂上shader,并没有产生材质球。

研究了一下发现,这种shader是依赖在scene文件中。

3.游戏的时候动态运用的shader,这种情况只要在c#文件中搜索,如果包含shader名字,说明shader是用到的。

3.思路

  根据上面的分析,我们先整理出一个框架,然后再开始写代码,这是一个好的习惯,在写代码之前先用中文把思路表达清楚,写起来

就不会乱了,扯远了哈,继续说框架。

1.指定目录,一般只要在项目的某个路径里执行就可以了 

1.查找出项目中所有的材质球,特点是文件名包含 “.mat”,将其文件路径加入到数组A 

2.查找出项目中所有的scene,特点是文件名包含“.unity”,将其文件路径加入到数组B

3.查找出项目中所有的shader,特点是文件名包含“.shader”,将其文件路径加入到数组C

4.查找出c#文件使用的shader,将其加到数组C里面

5.通过shaderGuid将引用在mat和scene的shader找出来,将其加入数组D

6.通过数组C与D ,得出没有用到的shader路径,将其加入到数组E

7.删除E

 这样我们就可以开始写代码了

4.代码

  里面的代码全部是加上详细注释的,应该不难看懂

using System.Collections;using System.Collections.Generic;using UnityEngine;using UnityEditor;using System.IO;using System.Text.RegularExpressions;public class DelectShader : EditorWindow{    private static List<string> matPahtList = new List<string>(); //所有的material路径数组    private static List<string> scenePathList = new List<string>();//所有的scene路径数组    private static List<string> allshaderPahtList = new List<string>();//所有shader路径数组    private static List<string> useShaderPathList = new List<string>();//所有用到的shader路径数组    private static List<string> noUseShaderList = new List<string>();//没用到shader路径    private static List<string> allCsPathList = new List<string>(); //所有c#数组    [MenuItem("Game-X/删除多余shader")]    //菜单调用这个函数    static void GetNotQuoteShaderPath()    {        instantPathList(); //实例化三个数组:1 所有的shader 2 在材质球中用到的shader 3 在scene中用到的shader        addMat();  // 将 在材质球中用到的shader + 到用到的shader数组里        addScene();// 将 在scene中用到的shader + 到用到的shader数组里        addCs();   // 将 在 c#中用到的shader + 到用到的shader数组里        noUseShader();//通过 “所有的shader” 和 “所有用到的shader” 得出没有用到的shader        deletes();//删除没有用到的shader    }    //获取所有的shader 和 mat 和 scene的路径    static void instantPathList()    {   //Application.dataPath:Assets路径  这里相当于“Assets/resourcex” 项目里用到的shader跟mat只在这个文件夹里面        string path = Application.dataPath+ "/resourcex";        //Directory.GetFiles():得到所有这个路径里包含.shader的文件。 得到文件夹用Directory.GetDirectories();        allshaderPahtList = new List<string>(Directory.GetFiles(path, "*.shader", SearchOption.AllDirectories));        matPahtList = new List<string>(Directory.GetFiles(path, "*.mat", SearchOption.AllDirectories));        scenePathList = new List<string>(Directory.GetFiles(path, "*.unity", SearchOption.AllDirectories));        //因为c#文件不一定在resourcex下面,所以把路径设为整个Assets        string pathCs = Application.dataPath;        allCsPathList = new List<string>(Directory.GetFiles(pathCs, "*.cs", SearchOption.AllDirectories));    }    /// <summary>    /// 通过shader的路径获取Shader的guid 在下面的 addMat() 与 addScene()中取shaderGUID时使用    /// </summary>    /// <param name="shaderPath"></param>    /// <returns></returns>    //通过shader的路径获取Shader的guid 在下面的 addMat() 与 addScene()中取shaderGUID时使用    static string FindShaderGuid(string shaderPath)    {   //得到shader guid的方法        return AssetDatabase.AssetPathToGUID(shaderPath);    }    /// 将材质用到的shader路径加到useShaderPathList数组里     //检查shaderGuid是否有引用在mat文件里 这个方法会在下面的addMat()方法中调用    static bool CheckGuidInMat(string shaderGuid)    {         for (int j = 0; j < matPahtList.Count; j++)        {            string matFilePath = matPahtList[j];           //搜索路径文件里是否包含 shaderguid,如果包含 则返回true            if (Regex.IsMatch(File.ReadAllText(matFilePath), shaderGuid))//在文件里查找是否有shaderGuid                          return true;                                                                                                                 }        return false;    }    //将材质用到的shader路径加到useShaderPathList数组里    static void addMat()    {        //遍历整个shader数组,将mat用到shader加到useShaderPathList数组里(要是里面没包含这个shader才需要加)        for (int i = 0; i < allshaderPahtList.Count; i++)        {   //得到shader的guid            string shaderGuid = FindShaderGuid(allshaderPahtList[i].Substring(allshaderPahtList[i].IndexOf("Assets")));            //如果shaderGuid不为空的时候            if (!string.IsNullOrEmpty(shaderGuid))            {                //上面的方法CheckGuidInMat()返回为true                if (CheckGuidInMat(shaderGuid))                {                    //如果useShaderPathList数组里没包含这个shader路径,将其加进数组                    if (!useShaderPathList.Contains(allshaderPahtList[i]))                        useShaderPathList.Add(allshaderPahtList[i]);                    Debug.Log("材质球中用到的shader有:" + allshaderPahtList[i]);                }            }        }    }    /// <summary>    /// 将scene用到的shader路径加到useShaderPathList数组里    /// </summary>    /// <param name="shaderGuid"></param>    /// <returns></returns>    //检查shaderGuid是否有引用在scene文件里 这个方法会在下面的addScene()方法中调用    static bool CheckGuidInScene (string shaderGuid)    {              for (int i = 0; i < scenePathList.Count; i++)        {            string SceneFilePath = scenePathList[i];            if (Regex.IsMatch(File.ReadAllText(SceneFilePath), shaderGuid))            return true;        }        return false;    }    //将scene用到的shader路径加到useShaderPathList数组里    static void addScene()    {        for (int i = 0; i < allshaderPahtList.Count; i++)        {            string shaderGuid = FindShaderGuid(allshaderPahtList[i].Substring(allshaderPahtList[i].IndexOf("Assets")));            if ((!string.IsNullOrEmpty(shaderGuid)))            {                if (CheckGuidInScene(shaderGuid))                {                    if (!useShaderPathList.Contains(allshaderPahtList[i]))                    {                        useShaderPathList.Add(allshaderPahtList[i]);                        Debug.Log("场景中用到的shader有:" + allshaderPahtList[i]);                    }                }            }        }    }    /// <summary>    /// 将所有cs用到的shader加入到数组    /// </summary>    /// <param name="Name"></param>    /// <returns></returns>    //检查c#是否被shader引用    //因为c#跟shader没有guid依赖关系,说以要根据shader名来查找    static bool CheckNameCs (string Name)    {   //遍历c#数组,如果他包含指定的shader名,返回true        for (int i = 0; i < allCsPathList.Count; i++)        {            string csPath = allCsPathList[i];                        if (Regex.IsMatch(File.ReadAllText(csPath), Name))                return true;        }        return false;    }    //将所有cs用到的shader加入到数组    static void addCs()    {        for (int i = 0; i < allshaderPahtList.Count; i++)        {   //得到shader数组里的shader名(不包含扩展名 ,即“.”后面的名字)            string Name = Path.GetFileNameWithoutExtension(allshaderPahtList[i]);            //给上面的方法输入shader名,如果返回为true            if (CheckNameCs(Name))            {   //如果useShaderPathList没包含这个shader,将其加到useShaderPathList数组里                if (!useShaderPathList.Contains(allshaderPahtList[i]))                {                    useShaderPathList.Add(allshaderPahtList[i]);                    Debug.Log("c#中用到的材质球有:" + allshaderPahtList[i]);                }            }        }    }       //通过所有的shader路径  很已经用到的shader路径  得出没用到的shader路径    static void noUseShader()    {        //遍历allshaderPahtList路径  如果 useShaderPathList没包含 将加到noUseShaderList路径里        for (int i = 0; i < allshaderPahtList.Count; i++)        {            string shaderPath = allshaderPahtList[i];            if (!useShaderPathList.Contains(allshaderPahtList[i]))            {                if (!noUseShaderList.Contains(allshaderPahtList[i]))                {                    noUseShaderList.Add(allshaderPahtList[i]);                }                            }        }    }    // 删除没有用到的shader    static void deletes()    {        for (int i = 0; i < noUseShaderList.Count; i++)        {            Debug.Log("删除的shader有:" + noUseShaderList[i]);            File.Delete(noUseShaderList[i]);        }    }}

阅读全文
0 0
原创粉丝点击