删除项目工程里的未使用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的主要内容,如果未能解决你的问题,请参考以下文章
Cg入门19:Fragment shader - 片段级模型动态变色