删除项目工程里的未使用Shader

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了删除项目工程里的未使用Shader相关的知识,希望对你有一定的参考价值。

1.描述

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

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

2.分析

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

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

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

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

3.游戏的时候动态运用的shader,这种情况对我来说比较复杂,暂时先不考虑。

3.思路

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

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

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

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

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

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

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

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

6.删除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路径
    [MenuItem("Tool/删除多余shader")]


    //菜单调用这个函数
    static void GetNotQuoteShaderPath()
    {
        instantPathList(); //实例化三个数组:1 所有的shader 2 在材质球中用到的shader 3 在scene中用到的shader
        addMat();  // 将 在材质球中用到的shader + 到用到的shader数组里
        addScene();// 将 在scene中用到的shader + 到用到的shader数组里
        noUseShader();//通过 “所有的shader” 和 “所有用到的shader” 得出没有用到的shader
        deletes();//删除没有用到的shader
    }




    //获取所有的shader 和 mat 和 scene的路径 在菜单的函数里调用
    static void instantPathList()
    {   //Application.dataPath:Asset路径  这里相当于“Asse/resourcex” 只需在这个文件夹里面
        string path = Application.dataPath+ "/resourcex";
        //Directory.GetFiles():得到所有这个路径里包含.shader的文件。
        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));
    }




    //检查shaderGuid是否有引用在mat文件里 这个方法会在下面的addMat()方法中调用
    static bool CheckGuidInMat(string shaderGuid)
    {
        string matFilePath = "";
        for (int j = 0; j < matPahtList.Count; j++)
        {
            matFilePath = matPahtList[j];
           //
            if (Regex.IsMatch(File.ReadAllText(matFilePath), shaderGuid))//在文件里查找是否有shaderGuid
                
                return true;                                             
                                                                        
        }
        return false;
    }

    //检查shaderGuid是否有引用在scene文件里 这个方法会在下面的addScene()方法中调用
    static bool CheckGuidInScene (string shaderGuid)
    {
        string SceneFilePath = "";
        for (int i = 0; i < scenePathList.Count; i++)
        {
            SceneFilePath = scenePathList[i];
            if (Regex.IsMatch(File.ReadAllText(SceneFilePath), shaderGuid))
            return true;
        }
        return false;
    }






    //通过shader的路径获取Shader的guid 在下面的 addMat() 与 addScene()中取shaderGUID时使用
    static string FindShaderGuid(string shaderPath)
    {
        return AssetDatabase.AssetPathToGUID(shaderPath);
    }


    //将材质用到的shader路径加到useShaderPathList数组里
    static void addMat()
    {
        for (int i = 0; i < allshaderPahtList.Count; i++)
        {
            string shaderGuid = FindShaderGuid(allshaderPahtList[i].Substring(allshaderPahtList[i].IndexOf("Assets")));
            if (!string.IsNullOrEmpty(shaderGuid))
            {
                if (CheckGuidInMat(shaderGuid))
                {
                    if (!useShaderPathList.Contains(allshaderPahtList[i]))
                        useShaderPathList.Add(allshaderPahtList[i]);
                }
                    
                   
            }

        }
    }

    //将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]);
                    }
                   
                }     
            }
        }
    }

    //通过所有的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]);
        }
    }





}

 

 5.实现原理

 

以上是关于删除项目工程里的未使用Shader的主要内容,如果未能解决你的问题,请参考以下文章

unity3d 如何代码修改某个shader的颜色

Shader HLSL片段说明

Cg入门19:Fragment shader - 片段级模型动态变色

Cg入门16:Fragment shader - 片段级光照

Shader2.0的顶点着色器和片段着色器

如何删除IntelliJ IDEA的未使用的导入上犯